diff --git a/.gitattributes b/.gitattributes index 6244d8c76d..016185bfd7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12,6 +12,10 @@ openpilot/selfdrive/modeld/models/big_*_tinygrad.pkl -text *.woff2 -text *.wav -text openpilot/starpilot/galaxy/web/vendor/vue/vue.esm-browser.js -text +openpilot/starpilot/companion/ios/GalaxyBluetooth/Resources/Web/vendor/vue/vue.esm-browser.js -text +*.apk -text +openpilot/starpilot/galaxy/bin/hev-socks5-tunnel_linux_arm64 -text +openpilot/starpilot/soloist/pulseaudio/bin/pulseaudio -text openpilot/selfdrive/car/tests/test_models_segs.txt -text openpilot/common/hardware/comma/updater -text diff --git a/.gitignore b/.gitignore index 5185710c44..757b67c705 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ a.out .venv-linux-arm64/ bin/ !openpilot/starpilot/galaxy/bin/ +!openpilot/starpilot/soloist/pulseaudio/bin/ # created at launch for comma hardware PYTHONPATH (PC uses editable installs via pyproject.toml) /msgq @@ -44,6 +45,8 @@ bin/ *.os-* *.so !openpilot/tools/replay/libmedia_mux.so +!openpilot/starpilot/soloist/pulseaudio/lib/*.so +!openpilot/starpilot/soloist/pulseaudio/modules/*.so *.a st[0-9A-Za-z][0-9A-Za-z][0-9A-Za-z][0-9A-Za-z][0-9A-Za-z][0-9A-Za-z] *.unchunked diff --git a/CREDITS.md b/CREDITS.md index fb01922527..ca32b66a7b 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -25,3 +25,7 @@ The vendored `opendbc_repo/opendbc/bluepilot_lateral` angle core, codecs and For ## RAV4 Continental ARS510 receiver The optional ACC-target and fused-track receivers and DBC preserve firestar5683's Dom integration from `b220a37f4bd119e402225a7aa16a7cd84878d0af` (Sea Turtles, 2026-10-13) and its ARS510 source attribution to ds-sebastian/ars510-radar `fb5b29c2b5999f34afeb6f7ac494a73949d66c67`, copyright 2026 ARS510 radar contributors. The complete MIT permission and warranty notice is retained in THIRD_PARTY_NOTICES.md. Startup/settings ownership is adapted to the current StarPilot architecture; no original firmware binaries or safety permissions are copied. + +## Spotify Bluetooth output + +Spotify's Bluetooth output binds the comma's BlueALSA A2DP source to the selected speaker through a process-local ALSA configuration, leaving the system ALSA default, soundd and the warning speaker untouched. That approach is adapted from firestar5683's RoadScore Bluetooth output (`roadscore/prototype/bluetooth_output.py`, firestar5683/StarPilot `RoadScore` at `249eb88b3a397db847e4a595d7e23b7e85d329e5`). The Soloist player itself is never included: each user downloads it from Spotify, and the PulseAudio server that carries its audio is vendored unmodified from Ubuntu (see THIRD_PARTY_NOTICES.md). diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index ae54dfa937..693b6e282e 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -112,3 +112,31 @@ 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. + +## PulseAudio server for Spotify + +`openpilot/starpilot/soloist/pulseaudio/` contains unmodified AArch64 binaries from Ubuntu 24.04 packages: PulseAudio 16.1 (LGPL-2.1-or-later), libltdl (LGPL-2.1-or-later), libtdb (LGPL-3.0-or-later), libsoxr (LGPL-2.1-or-later), liborc and speexdsp (BSD-style). The complete copyright and license notices are in that directory's `licenses/`, package hashes in `PACKAGES.sha512`, and the corresponding source is available from Ubuntu's archive for the exact versions listed in its README. The libraries are dynamically linked and may be replaced with `update.sh`. + +## Galaxy Android companion tunnel + +`openpilot/starpilot/galaxy/bin/hev-socks5-tunnel_linux_arm64` is the upstream +[hev-socks5-tunnel 2.18.0](https://github.com/heiher/hev-socks5-tunnel/releases/tag/2.18.0) +static Linux ARM64 release, under the MIT license. Its notice is retained in +`openpilot/starpilot/galaxy/bin/LICENSE.hev-socks5-tunnel`; the adjacent SHA-256 +file pins the downloaded artifact. The Android companion uses the Kotlin +standard library (Apache-2.0) and the Gradle wrapper (Apache-2.0); no third-party +UI framework is bundled. + +## Galaxy Bluetooth companion source snapshot + +The Galaxy Bluetooth phone bridge and iOS app from https://github.com/firestar5683/StarPilot +(natehuby76, PRs #224/#225) are included under `openpilot/starpilot/galaxy_bluetooth/` +and `openpilot/starpilot/companion/ios/`, with their license files (`UPSTREAM-LICENSE`, `openpilot/starpilot/companion/ios/UPSTREAM-GALAXY-LICENSE`). +The bridge runs on openpilot's Python with PyCryptodome 3.23.0 (BSD/public-domain +components, from opendbc). Its other dependencies are vendored unmodified, as +pure-Python sources, in `openpilot/starpilot/galaxy_bluetooth/vendor/`: +dbus-next 0.2.3 (MIT), ifaddr 0.2.0 (MIT) and Zeroconf 0.151.3 +(LGPL-2.1-or-later). Their license texts are in `vendor/licenses/`, and +`vendor/VENDOR.json` records each PyPI source file and its SHA-256. Zeroconf is +kept as separate, unmodified source files that can be replaced with another +compatible version, as the LGPL requires. diff --git a/mapd_repo/cereal/custom/custom.capnp b/mapd_repo/cereal/custom/custom.capnp index eb4836d593..020219b2ae 100644 --- a/mapd_repo/cereal/custom/custom.capnp +++ b/mapd_repo/cereal/custom/custom.capnp @@ -10,7 +10,12 @@ $Go.import("pfeifer.dev/mapd/cereal/custom"); # DO rename the structs # DON'T change the identifier (e.g. @0x81c2f05a394cf4af) -struct CustomReserved0 @0x81c2f05a394cf4af { +struct StarPilotCarControl @0x81c2f05a394cf4af { + # The first three fields are pointer slots mapd does not read. + hudControl @0 :AnyPointer; + steeringLimitInfo @1 :AnyPointer; + navigation @2 :AnyPointer; + phoneGps @3 :StarPilotCarState.Gps; # sourceMonoTime is comma receive time minus the phone's fix age } struct CustomReserved1 @0xaedffd8f31e7b55d { diff --git a/mapd_repo/cereal/custom/custom.capnp.go b/mapd_repo/cereal/custom/custom.capnp.go index c37214f7d9..32af399a4c 100644 --- a/mapd_repo/cereal/custom/custom.capnp.go +++ b/mapd_repo/cereal/custom/custom.capnp.go @@ -9,69 +9,137 @@ import ( math "math" ) -type CustomReserved0 capnp.Struct +type StarPilotCarControl capnp.Struct -// CustomReserved0_TypeID is the unique identifier for the type CustomReserved0. -const CustomReserved0_TypeID = 0x81c2f05a394cf4af +// StarPilotCarControl_TypeID is the unique identifier for the type StarPilotCarControl. +const StarPilotCarControl_TypeID = 0x81c2f05a394cf4af -func NewCustomReserved0(s *capnp.Segment) (CustomReserved0, error) { - st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return CustomReserved0(st), err +func NewStarPilotCarControl(s *capnp.Segment) (StarPilotCarControl, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 4}) + return StarPilotCarControl(st), err } -func NewRootCustomReserved0(s *capnp.Segment) (CustomReserved0, error) { - st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) - return CustomReserved0(st), err +func NewRootStarPilotCarControl(s *capnp.Segment) (StarPilotCarControl, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 4}) + return StarPilotCarControl(st), err } -func ReadRootCustomReserved0(msg *capnp.Message) (CustomReserved0, error) { +func ReadRootStarPilotCarControl(msg *capnp.Message) (StarPilotCarControl, error) { root, err := msg.Root() - return CustomReserved0(root.Struct()), err + return StarPilotCarControl(root.Struct()), err } -func (s CustomReserved0) String() string { +func (s StarPilotCarControl) String() string { str, _ := text.Marshal(0x81c2f05a394cf4af, capnp.Struct(s)) return str } -func (s CustomReserved0) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { +func (s StarPilotCarControl) EncodeAsPtr(seg *capnp.Segment) capnp.Ptr { return capnp.Struct(s).EncodeAsPtr(seg) } -func (CustomReserved0) DecodeFromPtr(p capnp.Ptr) CustomReserved0 { - return CustomReserved0(capnp.Struct{}.DecodeFromPtr(p)) +func (StarPilotCarControl) DecodeFromPtr(p capnp.Ptr) StarPilotCarControl { + return StarPilotCarControl(capnp.Struct{}.DecodeFromPtr(p)) } -func (s CustomReserved0) ToPtr() capnp.Ptr { +func (s StarPilotCarControl) ToPtr() capnp.Ptr { return capnp.Struct(s).ToPtr() } -func (s CustomReserved0) IsValid() bool { +func (s StarPilotCarControl) IsValid() bool { return capnp.Struct(s).IsValid() } -func (s CustomReserved0) Message() *capnp.Message { +func (s StarPilotCarControl) Message() *capnp.Message { return capnp.Struct(s).Message() } -func (s CustomReserved0) Segment() *capnp.Segment { +func (s StarPilotCarControl) Segment() *capnp.Segment { return capnp.Struct(s).Segment() } - -// CustomReserved0_List is a list of CustomReserved0. -type CustomReserved0_List = capnp.StructList[CustomReserved0] - -// NewCustomReserved0 creates a new list of CustomReserved0. -func NewCustomReserved0_List(s *capnp.Segment, sz int32) (CustomReserved0_List, error) { - l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) - return capnp.StructList[CustomReserved0](l), err +func (s StarPilotCarControl) HudControl() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(0) } -// CustomReserved0_Future is a wrapper for a CustomReserved0 promised by a client call. -type CustomReserved0_Future struct{ *capnp.Future } +func (s StarPilotCarControl) HasHudControl() bool { + return capnp.Struct(s).HasPtr(0) +} -func (f CustomReserved0_Future) Struct() (CustomReserved0, error) { +func (s StarPilotCarControl) SetHudControl(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(0, v) +} +func (s StarPilotCarControl) SteeringLimitInfo() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(1) +} + +func (s StarPilotCarControl) HasSteeringLimitInfo() bool { + return capnp.Struct(s).HasPtr(1) +} + +func (s StarPilotCarControl) SetSteeringLimitInfo(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(1, v) +} +func (s StarPilotCarControl) Navigation() (capnp.Ptr, error) { + return capnp.Struct(s).Ptr(2) +} + +func (s StarPilotCarControl) HasNavigation() bool { + return capnp.Struct(s).HasPtr(2) +} + +func (s StarPilotCarControl) SetNavigation(v capnp.Ptr) error { + return capnp.Struct(s).SetPtr(2, v) +} +func (s StarPilotCarControl) PhoneGps() (StarPilotCarState_Gps, error) { + p, err := capnp.Struct(s).Ptr(3) + return StarPilotCarState_Gps(p.Struct()), err +} + +func (s StarPilotCarControl) HasPhoneGps() bool { + return capnp.Struct(s).HasPtr(3) +} + +func (s StarPilotCarControl) SetPhoneGps(v StarPilotCarState_Gps) error { + return capnp.Struct(s).SetPtr(3, capnp.Struct(v).ToPtr()) +} + +// NewPhoneGps sets the phoneGps field to a newly +// allocated StarPilotCarState_Gps struct, preferring placement in s's segment. +func (s StarPilotCarControl) NewPhoneGps() (StarPilotCarState_Gps, error) { + ss, err := NewStarPilotCarState_Gps(capnp.Struct(s).Segment()) + if err != nil { + return StarPilotCarState_Gps{}, err + } + err = capnp.Struct(s).SetPtr(3, capnp.Struct(ss).ToPtr()) + return ss, err +} + +// StarPilotCarControl_List is a list of StarPilotCarControl. +type StarPilotCarControl_List = capnp.StructList[StarPilotCarControl] + +// NewStarPilotCarControl creates a new list of StarPilotCarControl. +func NewStarPilotCarControl_List(s *capnp.Segment, sz int32) (StarPilotCarControl_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 4}, sz) + return capnp.StructList[StarPilotCarControl](l), err +} + +// StarPilotCarControl_Future is a wrapper for a StarPilotCarControl promised by a client call. +type StarPilotCarControl_Future struct{ *capnp.Future } + +func (f StarPilotCarControl_Future) Struct() (StarPilotCarControl, error) { p, err := f.Future.Ptr() - return CustomReserved0(p.Struct()), err + return StarPilotCarControl(p.Struct()), err +} +func (p StarPilotCarControl_Future) HudControl() *capnp.Future { + return p.Future.Field(0, nil) +} +func (p StarPilotCarControl_Future) SteeringLimitInfo() *capnp.Future { + return p.Future.Field(1, nil) +} +func (p StarPilotCarControl_Future) Navigation() *capnp.Future { + return p.Future.Field(2, nil) +} +func (p StarPilotCarControl_Future) PhoneGps() StarPilotCarState_Gps_Future { + return StarPilotCarState_Gps_Future{Future: p.Future.Field(3, nil)} } type CustomReserved1 capnp.Struct @@ -3327,306 +3395,312 @@ func NewMapdOut_GpsSource_List(s *capnp.Segment, sz int32) (MapdOut_GpsSource_Li return capnp.NewEnumList[MapdOut_GpsSource](s, sz) } -const schema_b526ba661d550a59 = "x\xda\x94z\x0d\x90T\xd5\x95\xff9\xef\xf5L\xcf'" + - "M\xf3\x1a\x01\x01\xdb!\x928\xc41\xc0\xc8?\x0eh" + - "\x86\xa1g@\xa8\xeea\xde<>\x1c\x94\xaa\xdc\xe9w" + - "\xa7\xe7\xc1\x9b\xf7\x9a\xf7^\xcfLSX \x81*\xf4" + - "\x8f\x15\xcdj\x82)\xd9\xf8\x81\xb5\x9a\x95\x84du\x8b" + - "XX\x0b\x14\xa9B\x17\xaa4\xa5)c\xcc\xfaQ\xd9" + - "\xd2d\xb5\x8cY\xad5\xd9X\xbdu\xee\xed\xaf\xf9\x88" + - "8E\xd5t\xf7\xef\x9cw\xee\xb9\xe7\x9e{\xee\xf9\xdd" + - "\xc7r6\x7fmhE\xf3?\x8d\x81bdkjj" + - "\x0b\xd1\xdd\x03\xef:\xc1O\x0e@t!\x16\x06\x1a\xb6" + - ".\x1ez\xfe\xab\xcfA(\x0c\xd0\xfe\x8b5;P\xbb" + - "\xbc&\x0cj\xe1\xa7\x9f$;v\xfc\xe9\xfc\xdd\xd3h" + - "=MZ/\x08\xad\xdb\x13\xe7\xbf;\xf8\xd5\x1f\x1d\x86" + - "\xe8B\xa5\xa2\x05\xd8\xfe\xf0\x9aM\xa8\x9d\\#\xd5\xdd" + - "\x10`\xa1\xed\xc5\xdc\xed?^p\xdf\x03\xa0\xb7a}" + - "\xe1\xbc\xf3o\x8d\xdb.\xdc\xf9\xdfP\x83\xa4\xb3t\xed" + - "\xbd\xa8\xdd\xba\x96\xbev\xac}K\x01,\xfc\xe3\xd7?" + - "\xcaY{w|\x1f\xa2_Q\x0a\x07?\xfd\xf4+\xed" + - "\xff\xf5\xf1\x09\xb2\xbc'q\x10\xb5\xc3\x890\x80vw" + - "\xe2\x07\x80\x859\xcfb&s\xf1\xf2#\xd3x\xfaJ" + - "b\x10\xb5\xffL\x90\xa7m\xbf\x8d\xab\xdd\xe1\xe1\xc7\xa6" + - "\xd1:\x97\xd8\x81\xdakB\xcbV\xdb\xd7~6X\xfb" + - "\x04\xe8\x0b\xb1J\xadF\xe8\xfd\x8c\xf4~\x99\x90\x8fl" + - "G\xc0\x8a_\xfaB\x9cU\xa5^K:\xabz\xaeF" + - "\xad\xa7\xe7k\x00\xed\xacg,\x0cX\xe8N\x9c}\xe9" + - "\xe4[O<9%Z\x7fH\x1dD\xed\xf3\x14\xcd\xe9" + - "/\xa9o\x02\x16\xb6\x9e\xd0\x7fs\xc3\xe8\xe5'\xa7\xf1" + - "\xf6\xf3\xd4\x0e\xd4\xa2\xbd\xe4\xedO~\x9b~\xe8\xff?" + - "\xf5\xd1?O\xb1\xf7aju\xc5\xdef\xc0\xc2\xce\xe7" + - "\xde[\xf1\xdd\xcf\xdf\xfa\xc94\xf6\x9a{w\xa0\xd6\"" + - "\xecu\xbe\xf5\xc7\xbbR\xd7n?5\xed\xa8\x83\xa5Q" + - "/b\xb2\xc5J;\xa7\xa7\xd1\xfa\x90|C\xa15|" + - "\xe6\x1f\x1e4\xd6t\xbf0\x8d\xd6\xef\xc8\xd6\xc7)\xd2" + - ":\xa4\xde\xf46\xbf\xe5\xba\xf3\xd3h]&\xadw\x84" + - "\xd6G\xff\xf2\xadWn\xbeu\xd7\xc5\xc9\xab\xa2\x90\xde" + - "\x0b\xa99\xa8]\xa6\xb9\xb6\xbf\x98\x8a\xd3\xaa\xac\x1e\xd8" + - "\x9e\xb5_\xfb\xd1\xbfO7t/\x0d-\x1c|\xf9\xe0" + - "\xa3\x99\xff}\xe3\xfb\x97\xa7\x1b\x9a\xb4\xde\x11Z\x8b/" + - "\xa4\xdf|38\xf8\xca\x94\x10\xbf\xd0\xbb\x0e\xb5\xcb\xbd" + - "b\xd8^\x91\x0c\x1d\x1dg\x1e\xbbt\xef\xff\xfc\x9a\xbc" + - "T'o\xac\xcd\x9bP\xbb\xbc\x99\x16\xe4\xc5\xcd\xef\x01" + - "\x16V%\xbb\xbfsl\xfb\xf7\xdf\x98f\xf4\x93};" + - "P;\xd7G\xa3w|\xe7\xa5\x1f\xfe\xa0\xe6\x07\xffA" + - "&\x95Ij\xc7\xfb\xd6\xa1v\xb2\x8fL>\xdd7\x06" + - "X\xb8\xfe\x95_\x7ftC\xcf\xb3\x7f\x9e\xb2c\x9a\xf5" + - "]\xa8\xb5\xe8\xa4\xb9X\xcf\x00V6\xdfD\xb3r+" + - "n$\xed\x9d\xfa<\x80v\xae\x87)m\x17\x1c?\xbe" + - "\xb1\xfe\x83\xab>\x99\xc6\xd7\x91\x81\x1d\xa8\xdd=@\xbe" + - ">\x11\xca~\xbe\xe6\xd0}\x7f\x99Fk'i\xed\x11" + - "Z\xcb\xde_\xda\xfb\xde\x9d\xdf\xfa\xeb\x94x\xa6\x06\x06" + - "Qc\x03\xe4\xe4\xce\x81\xfd\x80\x85\xc7\xfd\xbe\x8b/\xed" + - "|\xe2\xaf\x93\x9d\x14\x8b~|\xe0 j?\x1b\x10\xe1" + - "\x1a\x10\xd1\x8f\xfe\xeb\xd8\x91\x0f\xbb\x06\xff6\xcd\xf0m" + - "w\x0c\xa2\xd6u\x07\x0d\xbf\xff\xd8\xa9\xf7\x8ccG\x0a" + - "\x933I\xcc|\xf1\x1d\xcf\xa3\xb6\xea\x0era\xc5\x1d" + - "?\x85\xc2\xdf\xfd\xf7P!\xcd=\xce\xeco\xa4C9" + - "?pG\xbe\x91\x16\x1f7\xa6Y\xd6\xc9\xaeN\x88\x1f" + - "\xfd\xdc\xe7\xde(W\xcd\x9b\xfa\x10g\xa2\xbf\xfcJ\xfa" + - ")\x9657:\xd9\\\xb0%\x9f\xe5\x00}\x88\xfa\x19" + - "T\x00\xb46e\x13\x00\xce\xd2Z\x95\x9f\x03`Dk" + - "U\x1e\x07\xc0\xd9Z\xab\xf2c\x00\x8cj\xad\xcay\x00" + - "\x9c\xa3\xb5*o\x00`\xa3\xd6\xa6\x0c\x02\xa0\xa6\xb5*" + - "/\x01`Lk\x13\x9f\xa8\xadP\xf6\x02\xa0\xa2\xb5)" + - "\xbb\x00p\xae\xd6*~_\xa5-U\xfe\x08\x80\xf3\xb4" + - "V\xe5W\x008_kS\xde\x05\xc0\x05\xda\x0a\xf1\xfb" + - "jm\x95\xf2C\x00\\\xa8\xad\x12\xe3.\xd2V\x09{" + - "\x8b\xb5\x0e\xf1\xfb\x1a\xadC\xf8\xa5\x16\x7f\x87\xb4\x0e\xe1" + - "O\\\xeb\x10v\xaf\xd5n\x15\xf6Z\xda\xbb\x94\xd5\x08" + - "\x805\xdaF\xe5y\x00\xac\xd56\x0a\x07\x9a\xb5\x1ee" + - "\x07\x006i]\xc2\xb1%\xda\xad\xe2\xc1\xafh]\xc2" + - "\xf0u\xc5\xcf\xa5\xed]\xca\x1c2\xd0\xa0mT\xee\x05" + - "\xc0\xafj\x1b\x95?\x03\xe0\xd7\xdaS\xca\x12\x12\\\xaf" + - "m\x15!hm\x1fP\x14\x02\x96\xb5\xef\x94_\xbe\xae" + - "1\xe5{\x00x\x83\xc6\xc4\xa3m\x1a\x13\xc1\x0b\x17\x7f" + - "\xd7iL9\x08\x80\xf5\xdaN\xf1y\xa36@>\x14" + - "Lw\xcc\xb1]f\x02@\xc1\xe7\xc1\x16\xe6e8\x06" + - "I\x16p\x8f\xd9\xf1\xaet\x9a\xdb\x84\x1bY\xceML" + - "Z#V\xb0yh(\xec\xf3`\x12\x9ap\x9dH\xe0" + - "\xb9B9\xc5\xb2\x89\\\x8d7\xca\x85<\xe1:$\x00" + - "\x9f\x07\xdb,\xdfr\x9dDn\x82H\x95\x0f%\xddL" + - "\x92CxT\x8e'4\x15\xa9*|\"\x97\xba\xa4\x8f" + - "\xd5\xb2\x94\xe5H\xf16\x80\x82\xc7i&\x06\x87\xce " + - "\xb0\x9c\x8c_\xf0\xd9(7x\x10@D\xfe\xe4A\x8f" + - "\xc3\x06m\xe8\x94\xc3O6\xb6\xd5\xe7B\xce\x8dHI" + - ",\xa6\xa2L\x90e9G\xb3<{E\xcc\xbeJ\x1a" + - ".>y\x9bk\x9bI\x85\xf9\x81\xc1\xb9#TI\x13" + - "\x83\xaa(\x0bt\x13W\xbd\xdd\x93\xc1\xaet\xb8\x18x" + - "\x81*\x12\xddb\x8d\xf0\xcdCC>\x0fd \xba\xf9" + - "\x10\xcb\xa1\x1d$\x99\xc3\xb7[a3\x18.\xbb\x8c\xa5" + - "\xb8\xc5E\xe0\x0a\x14\x18R\xc7\x9c\x1dPD\xac0\x05" + - "\x84\xd0~\x9evkFF\xb8crSH\x9c\x8cO" + - "ke\xd8\xeeX\xb7;\xe6\xacw\xbd^>.\x1dH" + - "Fh\xb2\x95\xb9o\xcdN\x90Z\xe1\xa2\x94\xe6n\xa8" + - "\xa59\x07\xdb\x87-\x9b'\x86\x99\x93\xb1\x9c\x8c\xc1;" + - "\xa5\xba\x18\xbd\x8f{>Z~\xc0\x9d\x80\x04r\xd9\xd2" + - "\xccIs\xbb\xdb\x85N\x99\x9b\xc5\xf4\xd8\xe4\x83\xea:" + - "\xc5\x1f\x86\x0b\x91\x9c\x97\xe6bQ\xc7\x03\xee)\x0e\xb3" + - "\xcba\x9e\x90\x8eB\x8c%q<9a\x0e2{\xfb" + - "<+\xeezV\x90/\xe3\xaa4CN\xf3~\xbe'" + - "gy\xdc\xa7\xdd\x90\xc5\xa0\xc0\xe830\xb2X\x1aM" + - ".G\x9f\xc7}_\xd9\xc0\xfc-nWQc\xc2x" + - "]\xe6\xae\x9c\xafR\xf8\xe5jVkUb'@%" + - "\xa8L\x85V\xddUsAy\x88z1\xc4\xe6Q\xee" + - "y\x96\xc9+\x8a\xb4j\x09\xd71\xad\xc0r'\x07\xa3" + - "\xb4\x03\x8daf\xbac\x09\xe6\x19\x01\x0bPDO@" + - "8\x96rMno[)\xa7R\xc46d\xfd\xa4\x9b" + - "f\x112H\xf0&\xdfu\xfa\x90\x05\xc3\xebm\x97\x15" + - "g-\xb0Z\x16\x0co\xe1\xe3\xc2\x05\x01\xb0`x\x9d" + - "[=d\xd1\x14Y\xa2\xf5\x88x\x0e\xb3\xcb\x87E\xcd" + - "4\x87\x85\x110\xaf\xcf\xb2\xdd\xa0\xe8,\xbfqC\xd6" + - "\x97\x87\xc6Mj\x08 \x84t\xe0\xe2^\x00\xe3NT" + - "\xd1\x18F\x05\xa3\x881$\x9c\xe3&\x00\xc3$\x15\x85\x81Y\x80_\x98\x96\xd4" + - "\xc3l\xce\x057\x1al$ksJ\xcc\x9c/\x92r" + - ">%X\xb4k\x1d5\"\xd1\x8e\x95\xd4\x87DW\xd0" + - "\xa9\xafF\xdb\x08\x0cE\x97R/P\x13m\xd9\x05\xb0" + - "?\xe7\xecv\xdc1'\xee\xb8\x1b\xb2~\xc1q\x13\xee" + - "(\xf7\x18\xa8\x19\xbe\xdfqS,H\x0f\x17F\xe8/" + - "7{\xa1\xd3\x95%\xa4\x08$AV\xe1/\xdd\x99\x85" + - "\xcd\x15+g\xd8\xcau|\x99V\x8e\xf61\x9d\x1a\x9b" + - "\xd5\\ \"P\xda\x96\xd1\x87\xef\x05\xd0\x1fQQ\x7f" + - "\xaa\xb2'\xa3On\x02\xd0O\xa8\xa8\x9f\xaal\xc8\xe8" + - "\xc9e\x00\xfaS*\xea\x17*\xbb1z\x8e4\xcf\xaa" + - "\xa8_R\x10Cb'F_<\x08\xa0_TQ\x7f" + - "\x95\xb6!\x8am\x18}e\x10@\x7fYE\xfdM\x05" + - "\xcb\x9d\x0c\xf6yn\x86\xea$\xb5\x90\x95f\x1c\x10g" + - "S\xd2\x94\x8e8\xea\xc7@\xc1&\xc0H\x96\x05\xc3\xa5" + - "\x1c\x98]aC\x80\"\x1b\xb2\xae/**\x08{e" + - "bS\xb4g\xbbn\xb6\x9f\x05\x1c\xbbh\x013\xbc\x92" + - "\xbb%\x09\x84S\x96SFKAU\xff^n\xa9\xb9" + - "@\xaf\xc3\xeak\x84\xfa]U\x0c\xa9\xbe\xbfPJ=" + - "\x88P\xf2\x156d}\x83\xf65 \xd7\x8f\x94+\xe3" + - "\xd3\xea:\xaa,*U\x16\xb5\xaa2\x9eT\xa9R<" + - "E\xf8\xb3jUe\xfc\x99J\x15\xf0\x14\xe1gT\x05" + - "\xb1X\x18\x7f\xa1R\xa1;M\xf0\x05R\x0f\xa1,\x8c" + - "\xe7T*\xbcg\x09\xbfDx\x8d\"\x0b\xe3\x8b\xea\xf3" + - "\x00\xc6%\xc2_'\xbcV\x95\x85\xf151\xec\xcb\x84" + - "\xbfIx8$\x0b\xe3o\x84\xfd\xd7\x09\xff=\xe1u" + - "\xaa,\x8c\xef\xa8T\x18\x7fO\xf8\x9f\x08\xaf\x0f\xc9\xc2" + - "\xf8\xa1J\x85\xf1\x03\xc2?#\xbc\xa1F\x16\xc6O\xd5" + - "\xef\x01\x18\x9f\x11\x1e\x0a)\x18m\xac\x95\x85\x11C\xbf" + - "\x020\xeaB*\x1a1\xc2\x9b\xde\x96\x951\x1a\"\x7f" + - "\x9a\x08\x9fOx\xf3\xe2\x186\x03hsCT\xf0g" + - "\x13\xbe\x88\xf0Y\xef\xc4p\x16\x80\xb6 D~\xce'" + - "\xfc:\xc2#u1\x8c\x00h-\xa1\x97\x00\x8c\xeb\x09" + - "\xbf\x89\xf0\xd9\xf51\x9cM4,D\xf1YN\xf8-" + - "\x84G\x1bb\x18\x05\xd0:B4\xaf[\x08\xbf\x8d\xf0" + - "9\x91\x18\xce\x01\xd0zB\x83\x00F7\xe1}\x84k" + - "\x8d1\xd4\x00\xb4T\xe8\xe7\x00F\x1f\xe1w\x12\x1ek" + - "\x8aa\x0c@\x1b\x08\xd1\x81r'\xe1\xc3\x84\xcfm\x8e" + - "\xe1\\:\xf8B\x14\x1f\x93\xf0,\xe1W-\x8a\xe1U" + - "t\xf0\x09\xfd,\xe1\xfb\x08\x9f\xf7n\x0c\xe7\x01hy" + - "\xe1\xcf>\xc2\x8f\x10>\x7fq\x0c\xe7\x03h\x87C\xbb" + - "\x00\x8cC\x84\xdfO\xf8\x82\xba\x18.\x00\xd0\xee\x13\xf1" + - "9B\xf8\x83\x84_]\x13\xc3\xab\x01\xb4\x07\x84\x9f\x0f" + - "\x12\xfe(\xe1\x0b\xaf\x89\xe1B\x00\xed\xb8\xf0\xe7\x11\xc2" + - "\x9f\"|Q<\x86\x8b\x00\xb4'E\x11\x9fg\x09?Kx\xbc1" + - "\x86q\x00\xed\x051\xaf\xb3\x84_\"\xfc\xda\xa6\x18^" + - "Ky(\xf0K\x84\xbfNxKs\x0c[(\x0fC" + - "\x07\x01\x8cW\x09\x7f;\xa4\xe0\xfe1\x96\xefe#\xbc" + - "T\x0a:\xc7X\xbe\x9f\x0f\x95~\x16<\x97\x99$\xaf" + - "\xaa\x16\xf2\xd8IZ#\xa0ZAy[;\xc5&\x18" + - ":e\xcb5E\x80\x12\xef\xb6:\xfd\x80\xda\xdb\x92B" + - "\xe70\xdb\xcb<\xb3l\x9d\xf4oc{\x19\xa8\xd3\x80" + - "\xe8\x99\xdd\x16=\xafV\x0c\x14\x989j\xf9\xae\x97\x87" + - "\xb81\xe1$\xa6\x87\xba\xccQ\x0bI(]\x98\"S" + - "J\xb2\xa2\xdd4V\x1cs\x1d\xbe\x9d\xe5K\x07e\xdc" + - "f\x0e\xf7\xb1\x16\x14\xac\x05,\x04\x96\xcd\x93D\x1bU" + - "n\x96T\xca\x91Q\xac\xc0\xc8e2\xdc\x0f\xb8)\x8c" + - "W\x9d\xe8~Q\x00\x9d\xe6Dw\xb9\x1fX#TH" + - "\xcd~\x97\x99\xdb-S\x0d\x86\xcbBZ\x07\xeab!" + - "\xcc\xc7\x03\x8cT\xee\x0f\x011\x02X0\xadbT\xd7" + - "{\xee\xc8v\x96O\xc4\xb9CM\x7f\xb9\xc7(\x12O" + - ",1\xcf*\x8fF\x88/y\xa3|r\xfc\xc6X\xde" + - "\xe06O#\x15\x7fyc\x81\x91\xca5Pq\xe4\xd2" + - "\x9c\xd1\x92\x9d{P\x1d\x90a+3<\xc6\xf2\x09\x88" + - "\xd8\xcc\xf71R\xb9\x94\x93O\xc7\xc7X~\xa3Yj" + - "M\x0a\xe9b\xf3>\x89\xabT2O\x14\xfem\x1c\xe2" + - "\x1eM\x07\xc3\xa0`\xb8\x18\x1d\xeaD@\xcd\xd1 \xe5" + - "\x93\xa3\xe8b\xa6r@`\xa4r\x94T\xa4)\xd7q" + - "\xb7@\xb8\xba!L\xbb#\xd9\\\xc0M\x142\x8bv" + - "@Y&\xbb\xc8\x0d\x1c\x1d\xee1y2\x96eY\xcf" + - "5si\xee\xa1\xc1}\xf2\xb1\"\xf9\xc2^\xbfLU" + - "$\xbd\x15\xd1\xa6\x96\xa2N4\x09\xd1\xd5\xa2\xa9\xaa_" + - "\x07@\xbb'\xb0\xd2\xfb\xb3\xdcKs'\x98IO\xb3" + - "\xaa\xba\xa7\x99\xee\xf8\xa5\xbcKt\xbaN\xc0\xc7E?" + - "\xd3$\x06_,;\xba\xb9\xcbDG\xd7\xbc\x0e`\xff" + - "\x90\xc7\xf9\x18\xcbG\xd2V\x90/ur3\xf1d\xc5" + - "\x8c\xba\xb1\xb0\xb9b\xa67q\xdf\x9c\xe9\x00\xabf\xfa" + - "\xc0\x8a+\x05S\xdc\xf5\xa1Cq\x8c\x95\xfb\xc2\xbb\xa8" + - "\xdb\x1bWQ?T\xd5\x17\xde\xbd\x12@\xdf\xa7\xa2~" + - "DA,\xb6\x85\x87\x97\x00\xe8\x07T\xd4\x8fR[8" + - "[\xb6\x85\xf7\xd0\xd3\x87T\xd4\xef\xaf4\"\xd1\xfb\xa8" + - "W<\xaa\xa2~L\xc1H\x90\xcfR\x8a\x97\xdf\xed\x14" + - "w\xd9\x10\xb1\xd5\xd2\xbe\x0e\xfb\x81W\xee\xfc\x06]\xd7" + - ".\xef\xd6]E\xe2Z]\xecg\x12\x93\xe53\x0db" + - "\xfb\x95\x1e\xb8\xadX?\xa8z\x88\xfdp\xb3\x88\xcec" + - "2%\x1f\xde$R\xf2\xa1]\x82d<\xb0R\x90\x8c" + - "{\xfa\x05\xc98L*\xb5\xd1\xbb\x06\x010\x1c\xcd\x13" + - "X\x17\xcdy\xb4S\xa3{\xe8\xb9\x86\xe8\x08=\xd7\x18" + - "\xb5\xe8\xa3)\xcaI\xb39\xca\xaa\xc8Ia\xc4\x0d\\" + - "o\x8c\xe5\x01\xa0\xf2=\x92\xb4\x9c\xdd\xf1\xc0\xcb9\xbb" + - "\x0b\xe2o\xd2r\x00w\xef\xcfz\xd6\x08\xf3\xf2\x85\xe2" + - "g\x12\xc2\x96\xb3\xbb\xe0s*j\xcc\x03\xccW\xbe\xc7" + - "\xf3d\xa3\x10\x10\xf1c\x9e0_\xfe.\xcc\x17rN" + - "\x9a\xe6lAd\xc8\xe2f\xc1\xe3\xbeer*\xff\x16" + - "\xb3\x0b\xb65j9\x19\xea\x7f=\xce\x83+\xd2\x14Z" + - "\xd2>\xd7r\x02yy0\xbb\x9c\x8d\x8cR\xe7\xdb*" + - "\xeavU6Z\xfd\x00\xfa\xb0\x8az@\xcdqH\xa6" + - "\xe3\x1e\x02\xb3*\xea\xfb(\x1dkd:\xe6\xf7V\x92" + - "\xf9K\x13\xe8t\xce\x1beA\xce\x83\xcaA[\x08\xe4" + - "\x05&\x87N\xdb\xa5\x922\x85+|\x89\x1d\xdf\xfee" + - "\x08[_\x89\xc9\x88\xd2Z\x8eC+\xc5\xe1z\x15\xf5" + - "\x9b\xaa\xe2\xb0\x82\xa6\xbc\\E\xfd\x96\x99\xcc\xee\x0a\x0e" + - "\x10q\x16tE\\\xdd\x89\xd5\x10\xf1m]&\x12\xba" + - "E&\xf4\xe2M\"\xa1\x17,\x01\x888\xae\xc3\x0b\x16" + - "\x9d\xe5\x0e\xb3)Q\xf8x\xf9{8\xcd\xbc/\x1cr" + - "\xc2\x15R$`\x01\xd7CX\xf5>7\x8aK\xc2\x1b" + - "\xb2\xbe~\xa0\xcc\x9a\xf6\xa8\xd4\xf6f\x89F\xec\xabf" + - "MyAk\xf6\x11~\xa4\x9a5\x1dV\xa9-=D" + - "\xf8\xfd\x84\xab(i\xd3}\xea\xe3\x00\xc6\xfd\x84?\"" + - "h\x93*i\xd3\xc3\xc2\xfe1\xc2O\x08\xda\x14\x92\xb4" + - "\xe91\x95\xda\xd2G\x09\x7fF\xd0\xa6\x1aI\x9b\x9e\x16" + - "v\x9e!\xfc\xb4\xa0M\xb5\x926=\xa7\x9e\x9f@\xcb" + - "\xea\xc2\x926\x9d\x13\xac\xef\x0c\xe1\x17\x05m\xaa\x93\xb4" + - "\xe9\x97\x82f] \xfceA\x9b\xea%m\xba,X" + - "_\x85\xae56H\xda\xf4\x9a\xf0\xf3U\xc2\xdf&\xbc" + - "\xa9Q\xd2\xa6\xdf\x09\x9a\xf56\xe1\x1f\x10\xde\xdc$i" + - "\xd3\x1fTj\xdb\xdf'\xfc\x13\xc2g5K\xda\xf4\xb1" + - "\xa0q\x9f\xa8*\xf6\x0b\xd64K\xb2\xa6\xcf\xc5\xb0\x7f" + - "#\xf5:\xc1\x9a\"\x925\xd5\x88.?D\xdd\xf9l" + - "\xc1\x9afK\xd6\xd4,XD\x85\xad\xcd\x89J\xd64" + - "7\xf4\xfc\x04V\xa6\xa9\x925\xb5\x84\xc8\xcd\xeb\x08_" + - ".X\xd3\x1c\xc9\x9a\xda\x84\x9d\x1b\x08\xbfY\xb0&M" + - "\xb2\xa6UB\xfff\xc2\xbb\x05k\x8aI\xd6\xd4%X" + - "M\x85\x95\xcd\x9b+YSJ\xd8I\x12~\xbb`M" + - "WI\xd6\xb4U\xb0\x8b-\x84\x7f[\xb0\xa6y\x925" + - "\xed\x14l\xb0\xc2\xd6\xae^+Y\x13\x17\xe3\x0e\x13\x1e" + - "\x08\xd6\xd4%Y\xd3\x1ea\xa7\xc2\xd6\x16\xad\x93\xac)" + - "/\xf0q\xc2\x0f\x09\xd6\x94\x90\xac\xe9n\x81\x1f \xfc" + - "\xa8`M\xdd\x925\xdd#\xfc,\xb35\x8cK\xd2\xf4" + - "@h\x09\x80q\x94\xe0c!\x05\xc5}\xb6\xdd\xe7q" + - "\x88\xf8~U\xf7\xca\xec1\x96\xf77;X|\x1b\xd4" + - "\xd3)^qT\x14\x06=\xb6\x9b'\xad\x0c\x84\x87\x03" + - "\xbf\x8c\x9a\xcc\x1f\x1et\x99\x87f\xd5\xcdv\xb9\xa6\x99" + - "|\xda\xb1\xca\x0d\xbc\xb8\xe1\xe6&L\x95$]'C" + - "\xd2\xf0t\xcf)\xdb\xb8\x97/iT?\xbf\x9f\xa7\xdd" + - "\x0d\x9cy\xe5'\x86\\/\xcd\x13.\x03\xd5\x0f\xca\xa0" + - "\xe5\xf71o7\xd1\x82\xca\xc0Y\x96\xf3y\x92\x05\x10" + - "\xa1\xc9O\x82]\x07E\xf5\xb3\x1c\x86v\x15\x01r\xbd" + - "`\x03g\x80\x95\xf1\x02\x8f\x0d\x0dY\xe9\x14\xba\xa6|" + - "GTM\x102\xcc7\x02\x96\xde]=\xee\x88kr" + - "\x9a\x05L\x98\xa8,l}\x1e\xc4\xf9\x17.RW\xa7" + - "m\xbbc\xd5\x11\xaa,G\xe0f\x0d+\x83N\x99\xc5" + - "\xc9\x17-S\x8dJ<\xe9b)\x9e8Y\xb6\x8dc" + - ")\xde\x93\x9e\xcdr\x93\xd9)6\x0e\xf1~\x9e\xe1\xce" + - "D\\\xc4\xad+\x1dX\xa3\xbc2\xe1\x80\xfb6K$" + - "z\xa0\xd3\xc9\xb0L\x95\xa9\xa2\xa0\x1b-\x9f\x0b\x11N" + - "\x91\xf5\xa2\x1bty#\xd5\x09#\xb2\xf96\x9ap\xc2" + - "\xcbY~\xd5@\"\xf7\xa6\x95ds\xb6\xcf\xbb\x1c\x13" + - "\xe2\x1bl\xcb\xe4%<\x9c\xc9\xfa8\xbbr`\x14\xef" + - "\xfcfp.\xdf<\xc3\xce\xfd\xff]I\x7f{\x91\x95" + - "\x0aR\x1a\xceg\xc5)*\xbb\x94U\xb2-l\xeb\x17" + - "\xa7h\xab\x08\xeaZ^\x83\x1ej\xee\xbaU\xd4\xfb\x14" + - ",-A\x8a\xa2\x9dTQ\xbf\xbdj\x09\xb6R\x10\xb7" + - "\xa8\xa8\x7f[\xa9\x9ar\x15\x15\x9aY\xd4\xfe/\x00\x00" + - "\xff\xff\x00\xd1\x99X" +const schema_b526ba661d550a59 = "x\xda\x94Z}lT\xd7\x95?\xe7\xbd\xb1\xc7\x9f\x8c" + + "\x877\x04\x0c&\x13(\xd0\x98\xc6i\x8c\xf16\xa6I" + + "]c\x03\xc1\x1a\x83\xc7\xc3G@A\xea\xf5\xbc\xeb\x99" + + "\x07\xcf\xefM\xde{c{\x10\x11\x84\x82\x04YP\x93" + + "n\xd2\x92*lC\x02R\xda\x0d-\xed\x86\x15\x1bQ" + + "-AD\"Y\x90\x92\xaa\xa9\x9a4\xbbI\xa3JI" + + "\xba\x89\xd2v\x13m\xb6\xdb\xe8\xad\xce\xbd\xf3\xf1\xfc\xd1" + + "\x10\xff\xc3\xf8\xfd\xcey\xe7\x9e{\xee\xb9\xe7\x9e\xdf}" + + "\xdc\xf1\xf5\xfao\x86\xda\x1b3\x0d\xa0$\x1f\xae\xaa\xf6" + + "\xa3{v\xbccy?9\x00\xd1E\xe8\xef\xa8\xdb\xba" + + "x\xe4\xf9\x15\xe7!\x14\x06\xe8h\xae\xde\x89Z[u" + + "\x18T\xff\xa7\x1f'\xbav\xfe\xf1\xf2\x83\x93\xb5\xaa\x84" + + "Zm\xf5^\xd4\x16W\x87\x01\xb4\xe6\xeaw\x01\xfd{" + + "{/\x7fgx\xc5\x0f\x0fCt\x91RQ\x06\xec\xc0" + + "p?j\xf3\xc2\xf4R4l\x87\x00\xfd\xb6\x97\xf2\xf7" + + "\xfe\xb8\xf9\xf8#\x90l\xc3Z\xff\xb2\xf5o\xf5\xdb\xae" + + "\xdc\xf7\xdfP\x85\xa4s\xbc\xfe!\xd4\xce\xd4\xd3\x9f\xa7" + + "\xea\xdfR\x00\xfd\x7f\xfc\xcaGyc\xef\xce\xefA\xf4" + + "K\x8a\x7f\xf0\x93O\xbe\xd4\xf1_\x7f:M\x96_\x9f" + + "s\x10\xb5\x0f\xe7\x90\x0f\xef\xcf\xf9>\xa0?\xf79\xcc" + + "d\xae^\x7fb\x86iuE\x86Q\x1b\x88\xd0\xb4\xda" + + "~\x1bW\xfb\xc2\xd9S3h\xb5Fv\xa2v\xb7\xd0" + + "2\xd5\x8eo~:\\\xfd4$\x17\xe1\xb4\xd97\x93" + + "^[D\xbe\xb2\x1d\x01+~%\x17\xe1\x9c\x80:E" + + "\xa8\xe3d\xd3B\xd4\xce6}\x19\xa0\xe3\xa5\xa6\xf10" + + "\xa0\xdf\xd7{\xe9\xe5\xb3o=}fZ\xb4\x92\xcd\x07" + + "Q\xe3\xcd4'\xd6\xfc5@\x7f\xeb\xe9\xe4\xeb\xb7\x8d" + + "]?3\x83\xb7\xbcy'j\x85f\xf2\xf6'\xbfM" + + "?\xf6\xf7\xcf|\xf4O\xd3\xecmm^S\xb1\xb7\x19" + + "\xd0\xdfu\xfe\xdd\xf6\xef|\xf6\xd6Of\xb0\x97'{" + + "G\x85\xbd\xee\xb7\xfe\xf0\xc0\xc0-\xdb\xcf\xcd8\xeap" + + "i\xd4\xab\x98Xb\xa4\xad\x0b3hm%[\x86\xd0" + + "\xca^\xfc\x87GS_\xef\xfb\xc5\x0cZ\xeb\xc8\xd6\x0e" + + "\xa1uH]\xfd6\xbfk\xd9\xe5\x19\xb4:Ik\xa3" + + "\xd0\xfa\xe8\x9f\xbf\xf1\xea\x9dw\xef\xbe:uU\x14\xd2" + + "[\xde<\x17\xb5N\x9akG{s\x9cVe\xcd\x8e" + + "\xed9\xf3\xb5\x1f\xfe\xfbLC/\xa4\xa1\x17\x92\xd1W" + + "\x0e>\x99\xf9\xbf7\xbew}\xa6\xa1Ik\xa3\xd0Z" + + "|%\xfd\xe6\x9b\xde\xc1W\xa7\x85x\xf9\xc2\xb5\xa8u" + + ".\x14\xc3.\x14\xc9\xd0\xd5u\xf1\xd4\xb5\x87\xfe\xe7\xd7" + + "\xe4\xa5:\xc5\xe2\x92E\xfd\xa8u.\xa2\x05i_D" + + "\x1b\xa73\xd1\xf7\xed\x13\xdb\xbf\xf7\xc6\x0c\xa3\xcfk\xd9" + + "\x89Zk\x0b\x8d\xde\xf5\xed\x97\x7f\xf0\xfd\xaa\xef\xff'" + + "\x99T\xa6\xa8U\xb5\xacEm^\x0b\x99\x8c\xb6\x8c\x03" + + "\xfa\xb7\xbe\xfa\xeb\x8fn[\xf7\xdc\x9f\xa7\xed\x98|\xcb" + + "n\xd4\x8e\x0a\xcd\xc3-\x19\xc0\xca\xe6\x9blVn\xc5" + + "\x9f\x91\xf6\x8b-\xf3\x01:\xae\xb7\x84)m\x9bO\x9e" + + "\xdcX\xfb\xc1M\x1f\xcf\xe0\xebk\xcbv\xa2\xf6\xfe2" + + "\xf2\xf5\xe9P\xee\xb3\xaf\x1f:\xfe\xbf3h\xbdHZ" + + "\xaf\x0b\xad\x95\xef-\xdf\xf4\xee}\xdf\xf8\xcb\xb4x\x9e" + + "_6\x8c\xdaK\xcb\xc8\xc9\x17\x97\xed\x07\xf4\x9fr\x07" + + "\xaf\xbe\xbc\xeb\xe9\xbfLuR,z\xd5\xf2\x83\xa85" + + "/\x17\xe1Z.\xa2\x1f\xfd\x97\xf1#\x1f\xf6\x0c\xffu" + + "\x86\xe1\x1f[1\x8c\xda\x8fV\xd0\xf0\xfbO\x9c{7" + + "u\xe2\x88?5\x93\xc4\xcc\x0f\xafx\x1e\xb5\x93+\xc8" + + "\x85\xc7W\xfc\x14\xda\xfc4w83\xbf\x9a\x0e\xe5]" + + "\xcf\x1e\xfdjZ\xfc\xdc\x9ef9+\xb7\xa6W<\x0c" + + "q\x97;c\\\xd5W\x0f\"~\xae~\xcac\xce\xa0" + + "a\xda^/sz\xbbm\xcbsls\x101\xd9\xa4" + + "\x86\x00B\x08\x10e;\x01\x92\xdfR1i*\x18E" + + "\x8c!\x81\xc6w\x01\x92\xa6\x8a\xc9\x09\x05\xa3\x8a\x12C" + + "\x05 \x9a'MO\xc5\xe4\x01\x05\xa3\xaa\x1aC\x15 " + + "\xfa@?@r\x9f\x8a\xc9#\x0a\xfa\xd9\xbc\xdeKc" + + "\x80j\x9b8\x17\x14\x9c\x0b\xe8\xbb\x1e\xe7\x8eae0" + + "a\x8c\x1a\xdeFk\x04\xed\xb2\xccbcF\x86y\x06" + + "\xa8\xb6U\x06sY\xdb\xe2\x1br.\x00`S\xa5\x80" + + "\x03b\x13|\xfel\x07XN\xdfh\xe5\xf2\xde\x96B" + + "\x8e\x03\xd0D/\x92\xebZ\x9b\xd2\x0f\x80s\xb4V\xe5" + + "\xe7\x00\x18\xd1Z\x95\xa7\xc8\xb8\xd6\xaa\xfc\x18\x00\xa3Z" + + "\xabr\x19\x00\xe7j\xad\xca\x1b\x00X\xaf\xb5)\xc3\x00" + + "\xa8i\xad\xca\xcb\x00\x18\xd3\xda\xc4/j\xed\xca^\x00" + + "T\xb46e7\x00\xce\xd3Z\xc5\xf3M\xdar\xe5\x0f" + + "\x008_kU~\x09\x80\x0b\xb46\xe5\x1d\x00l\xd6" + + "\xda\xc5\xf3B\xadS\xf9\x01\x00.\xd2:\xc5\xb8-Z" + + "\xa7\xb0\xb7X\xeb\x12\xcf7k]\xc2/\xb5\xf8\x1c\xd2" + + "\xba\x84?q\xadK\xd8\xbdE\xbb[\xd8[\xd2\xd1\xa3" + + "\xacA\x00\xac\xd26*\xcf\x03`\xb5\xb6Q8\xd0\xa8" + + "\xadSv\x02`\x83\xd6#\x1c[\xaa\xdd-^\xfc\x92" + + "\xd6#\x0c/+\xfe.\xef\xe8Q\xe6\x92\x81:m\xa3" + + "\xf2\x10\x00\xae\xd06*\x7f\x06\xc0/w\x0c(KI" + + "p\xab\xb6U\x84\xa0\xb5c\x87\xa2\x10\xb0\xb2c\x97\xfc" + + "\xe3+\x1aS\xbe\x0b\x80\xb7iL\xbc\xda\xa61\x11\xbc" + + "p\xf1\xb9Fc\xcaA\x00\xac\xd5v\x89\xdf\xdb\xb5\x1d" + + "\xe4\x83\xaf\xdb\xe3\x96i3\x1d\x00|\x97{[\x98\x93" + + "\xe1\xe8%\x98\xc7\x1df\xc6{\xd2in\x12\x9e\xcaq" + + "\xae\xcb\x14\xd9<2\x12v\xb97\x05\xed\xb5\xad\x08e" + + "/\xc1\x03,\xd7\x9b\xafr\xc6\xb8\x90\xf7\xca\xb4\x06\x97" + + "{\xdb\x0c\xd7\xb0\xad\xde\xfc$\x91*_J\xd8\x99\x04" + + "\x87\xf0\x98\x1cOh*RU\xf8D.\xf5H\x1f\x83" + + "\xb2\x01\xc3\x92\xe2m\x00\xbe\xc3i&)\x0e\xdd\x9eg" + + "X\x19\xd7w\xd9\x18Oq\xcf\x83\x88|\xe4\xde:\x8b" + + "\x0d\x9b\xd0-\x87\x9fjl\xab\xcb\x85\x9c\xa7\"%\xb1" + + "\x98\x8a2I\x96\xe3\x1c\xf5\xf2\xec\x151\xfb\x804\\" + + "|\xf3\x1e\xdb\xd4\x13\x0as\xbd\x14\xe7\x96P%M\xf4" + + "\x02Q\x16h?W\x9d=S\xc1\x9et\xb8\x18x\x81" + + "*\x12\xddb\x8c\xf2\xcd##.\xf7d \xfa\xf8\x08" + + "\xcb\xa3\xe9%\x98\xc5\xb7\x1ba\xdd\xcb\x96]\xc6R\xdc" + + "\xe2\"p>\x05\x86\xd41oz\x14\x11#L\x01!" + + "t\x88\xa7\xed\xaa\xd1Qn\xe9\\\x17\x12+\xe3\xd2Z" + + "\xa5L{\xbc\xcf\x1e\xb7\xd6\xdb\xce&>!\x1dHD" + + "h\xb2\x95\xb9o\xcdM\x92\x1a\xe1\xa2\x94\xe6\x9eRK" + + "s\xf6\xb6g\x0d\x93\xf7f\x99\x951\xacL\x8awK" + + "u1\xfa w\\4\\\x8f[\x1e\x09\xe4\xb2\xa5\x99" + + "\x95\xe6f\x9f\x0d\xdd27\x8b\xe9\xd1\xefR\x1d*>" + + "\xa4l\x88\xe4\x9d4\x17\x8b:\xe1qG\xb1\x98Y\x0e" + + "\xf3\xa4t\x14b,\x89\xe3\x89Is\x90\xd9;\xe8\x18" + + "q\xdb1\xbcB\x19W\xa5\x19r\x9a\x0f\xf1\xfb\xf3\x86" + + "\xc3]\xda\x0d9\xf4|F\xbf^*\x87\xa5\xd1\xe4r" + + "\x0c:\xdcu\x95\x0d\xcc\xddb\xf7\x145&\x8d\xd7\xa3" + + "\xef\xce\xbb*\x85_\xaefP\xab\x12;\x01*^e" + + "*\xb4\xea\xb6\x9a\xf7\xcaC\xd4\x8a!6\x8fq\xc71" + + "t^Q\xa4U\xeb\xb5-\xdd\xf0\x0c{j0J;" + + "0\x95e\xba=\xde\xcb\x9c\x94\xc7<\x14\xd1\x13\x10\x8e" + + "\x0f\xd8:7\xb7\xad\x92S)b\x1brn\xc2N\xb3" + + "\x08\x19$\xb8\xdf\xb5\xadAd^v\xbdi\xb3\xe2\xac" + + "\x05V\xcd\xbc\xec\x16>!\\\x10\x00\xf3\xb2k\xed\xe0" + + "\x90ESd\x89\xd6#\xe2X\xcc,\x1f\x16U78" + + "\x1a\xc9Y~\xbb8s\xe8\xd0X]:\x1d\xb5]\xb8" + + "\x17 u\x1f\xaa\x98\xcab\xe5\x80\xd48\xf6\x03\xa4t" + + "\xc2sX9#\xb5Q\x1c\x02H\x99\x84O`\xe5\x98" + + "\xd4\xf2B\xdf#\xfc\x00\xe1\xa1\x9a\x18\x86\x00\xb4\x07p" + + "\x15@j\x82\xf0C\x84W\xd5\xc6\xb0\x0a@{\x10w" + + "\x02\xa4\x0e\x10~\x8c\xf0\xea\xba\x18V\x03hG\xf1\x07" + + "\x00\xa9c\x84\x9f <\\\x1f\xa3&B{\x0c\x1f\x02" + + "H\x9d \xfc4\xe15\x0d1\xac\x01\xd0N\x09\xfd\xd3" + + "\x84\x9f#\xbc\xb61\x86\xb5\x00\xdaYt\x00R\xcf\x12" + + "~\x81\xf0\xbap\x0c\xeb\x00\xb4\xf3\xf8\x14@\xea\x02\xe1" + + "WP\xc1%\xf5J\x0c\xeb\x01\xb4\x17p\x0d@\xea\"" + + "\xe1WQAl\x88a\x03\xf5L\xb8\x12 u\x89\xe0" + + "7QA\xdf\xb5i\xcb\x0c\xd8\xd0m\xd9\x94VX\x0b" + + "\x0a\xd6\x02\xfa&\xf3\x0c/\xafs:\xd3\xebA\xc1z" + + "\xc2l+C /c\xcc\x9c\xa6\x17w\xc56\xaa" + + "\x03\x05\xeb\x00\xfda\xce\xa8\x9b\xe8\x03\x95g\xca`\xd6" + + "v\x8c\xbd\xb6\xe5!3{\xd2\xe9\xbc\xc3\xd4t\xa1," + + "\x1c\xe3\x8eg\xa4\x99\x89R\x94.\xd0\x018\xd9Z\x0f" + + "\x16E}A\xab\xae\xac\x94i\x88\x0bY\x19\xcf[\xc6" + + "\x84\x98\x9d\xeb\xb1\xd1\xdc\x80a\x86M\xc3\xc5*P\xb0" + + "\x0a\xb0;\xcb\xdc\xf5\xc6\x04\"(\x88\x80\x91\xb1M\xeb" + + "\xfap\x0e\xe0\xa0\x8a\xc2\xc0\x9c@\x0fS\xf57z\x98" + + "\xcdy\xef\xf6\x14\x1b\xcd\x99\x9c\x123\xef\x8a\xa4\\ " + + "\x9a\xb0\x9e\xb5\xd4\x88D\xbbVQ\x1f\x12m\xa7S_" + + "\x8d\xb6\x11\x18\x8a.\xa7^\xa0*\xbad7\xc0\xfe\xbc" + + "\xb5\xc7\xb2\xc7\xad\xb8eo\xc8\xb9\xbee\xf7\xdac\xdc" + + "a\xa0f\xf8~\xcb\x1e`^:\xeb\x8f\xd2\xbf\\\xdf" + + "\x04\xdd\xb6,!E \x01\xb2\x0a\x7f\xe1>4\xac\xb7" + + "\xaf\xbaQ#:\xa5q\xed\xba\x91>\x85\x81\xf61\x9d" + + "\x1a\x9b\xd5\xbc'\"PnZ\x1f\x7f\x08 \xf9\x84\x8a" + + "\xc9g\x02M\xeb\x19jEO\xab\x98<\x17hZ\xcf" + + "\xae\x04H>\xa3b\xf2J\xa0i}\x814/\xa9\x98" + + "\xbc\xa6 \x86\xc4N\x8c\xbet\x10 yU\xc5\xe4\xaf" + + "h\x1b\xa2\xd8\x86\xd1W\x87\x01\x92\xaf\xa8\x98|S\xc1" + + "r'\x83\x83\x8e\x9d\xa1:)\xfa\xd32a(\xf6\xa7" + + "n\xe9\x88\xa3~\x0c\x14l\x00\x8c\xe4\x98\x97-\xe5@" + + "S\x85\xb1\x01\x8al\xc8\xd9\xae\xa8\xa8\xb2\xdf-\x93\xaf" + + "\xa2=\xd3\xb6sC\xcc\xe3\xd8C\x0b\x98\xe1\x95\xdc-" + + "I <`Xe\xb4\x14T\xf5o\xe5\x96\x9a\xf7\x92" + + "5\x18\xbc\xea\xa8\xdd\x1d`q\xb5C~)\xf5 B" + + "\xc9\xe7o\xc8\xb9)\xda\xd7\x80\x0f\x90" + + "\xbaF\xf8o\x08\xafVea|M\x0c\xfb\x0a\xe1o" + + "\x12\x1e\x0e\xc9\xc2\xf8\xba\xb0\xff\x1b\xc2\x7fOx\x8d*" + + "\x0b\xe3\xefT*\x8c\xbf'\xfc\x8f\x84\xd7\x86da\xfc" + + "P\xa5\xc2\xf8\x01\xe1\x9f\x12^W%\x0b\xe3'\xeaw" + + "\x01R\x9f\x12\x1e\x0a)\x18\xad\xaf\x96\x85\x11C\xbf\x04" + + "H\xd5\x84TL\xc5\x08ox[V\xc6h\x88\xfci" + + " |\x01\xe1\x8d\x8bc\xd8\x08\xa0\xcd\x0bQ\xc1o\"" + + "\xbc\x85\xf09\xbf\x8b\xe1\x1c\x00\xad9D~. |" + + "\x19\xe1\x91\x9a\x18F\x00\xb4%\xa1\x97\x01R\xb7\x12\xbe" + + "\x9a\xf0\xa6\xda\x186\x11\x9f\x0fQ|\xee \xfc.\xc2" + + "\xa3u1\x8c\x02h]!\x9a\xd7]\x84\xdfC\xf8\xdc" + + "H\x0c\xe7\x02h\xebB\xc3\x00\xa9>\xc2\x07\x09\xd7\xea" + + "c\xa8\x01h\x03\xa1\x9f\x03\xa4\x06\x09\xbf\x8f\xf0XC" + + "\x0cc\x00\xda\x8e\x10\x1d(\xf7\x11\x9e%|^c\x0c" + + "\xe7\xd1\xc1\x17\xa2\xf8\xe8\x84\xe7\x08\xbf\xa9%\x867\xd1" + + "\xc1'\xf4s\x84\xef#|\xfe;1\x9c\x0f\xa0\x15\x84" + + "?\xfb\x08?B\xf8\x82\xc51\\\x00\xa0\x1d\x0e\xed\x06" + + "H\x1d\"\xfca\xc2\x9bkb\xd8\x0c\xa0\x1d\x17\xf19" + + "B\xf8\xa3\x84/\xac\x8a\xe1B\x00\xed\x11\xe1\xe7\xa3\x84" + + "?I\xf8\xa2\x9bc\xb8\x08@;)\xfcy\x82\xf0g" + + "\x08o\x89\xc7\xb0\x05@;#\xe2y\x9a\xf0s\x84/" + + "^\x16\xc3\xc5\x94\x9e!:\xa0\x9f%\xfc\x02\xe17\xd7" + + "\xc5\xf0f:\xf8D|\x9e#\xfc\x12\xe1\xf1\xfa\x18\xc6" + + "\x01\xb4_\x88y]\"\xfc\x1a\xe1\xb74\xc4\xf0\x16\xca" + + "C\x81_#\xfc7\x84/i\x8c\xe1\x12\xca\xc3\xd0A" + + "\x80\xd4\xaf\x08\x7f;\xa4\xe0\xfeqV\xd8\xc4Fy\xa9" + + "\x14t\x8f\xb3\xc2\x10\x1f)=\xfa\x8e\xcdt\x92\x07\xaa" + + "\x85f \x09\xa5\x0b\xd3dJI" + + "V\xb4\x9b\xc6\x8ac\xb6\xc5\xb7\xb3B\xe9\xa0\x8c\x9b\xcc" + + "\xe2.V\x83\x82\xd5\x80\xbeg\x98" + + "\xe1a\xa4r\xc7\x09\x88\x11@_7\x8aQ]\xef\xd8" + + "\xa3\xdbY\xa17\xce-j\xfa\xcb=F\x91xb\x89" + + "y\x06<\x1a%\xbe\xe4\x8c\xf1\xa9\xf1\x1bg\x85\x147" + + "y\x1a\xa9\xf8\xcb\x1b\x0b\x8cT\xae\xaa\x8a#\x97\xe6\x8c" + + "\x86\xec\xdc\xbd`@\xb2F&;\xce\x0a\xbd\x101\x99" + + "\xebb\xa4rq(\xdf\x8e\x8f\xb3\xc2F\xbd\xd4\x9a\xf8" + + "\xe9b\xf3>\x85\xabT2O\x14\xfem\x1c\xe2\x0eM" + + "\x07\xc3\xa0`\xb8\x18\x1d\xeaD@\xcd\xd3 \xe5\x93\xa3" + + "\xe8b\xa6r@`\xa4r\x94T\xa4\x03\xb6eo\x81" + + "p\xb0!L\xdb\xa3\xb9\xbc\xc7u\x142\x83v@Y" + + "&\xbb\xc8\x0d\x1c-\xee0y2\x96e9\xc7\xd6\xf3" + + "i\xee`\x8a\xbb\xe4cE\xf2\xb9\xbd~\x99\xaaHz" + + "+\xa2M-E\x8dh\x12\xa2kDSU\xbb\x16\x80" + + "v\x8fg\xa4\xf7\xe7\xb8\x93\xe6\x967\x9b\x9e\xa63\xd8" + + "\xd3\xcct\xfcR\xde\x89K8>!\xfa\x99\x061\xf8" + + "b\xd9\xd1\xcd[):\xba\xc6\xb5\x00\xfbG\x1c\xce\xc7" + + "Y!\x926\xbcB\xa9\x93\x9b\x8d'\xed\xb3\xea\xc6\xc2" + + "z\xfb\xeaY\xb6o_\x9b\xed\x00\x9d\xb3}\xa1\xfdF" + + "\xc1\x14w}hQ\x1cc\xe5\xbe\xf0\x01\xea\xf6&T" + + "L\x1e\x0a\xf4\x85\x0f\xae\xaa\\Qb\xb1-<\xbc\x14" + + " y@\xc5\xe41j\x0b\x9bd[x\x94\xde>\xa4" + + "b\xf2\xe1J#\x12=N\xbd\xe21\x15\x93'\x14\x8c" + + "x\x85\x1c\xa5x\xf9\xfbSq\x97\x8d\x10[-\xed\xeb" + + "\xb0\xeb9\xe5\xceo\xd8\xb6\xcd\xf2n\xdd]$\xae\xc1" + + "b?\x9b\x98\xdc1\xdb v\xdc\xe8\x85{\x8a\xf5\x83" + + "\xaa\x87\xd8\x0fw\x8a\xe8\x9c\x92)\xf9x\xbfH\xc9\xc7" + + "v\x0b\x92\xf1\xc8*A2\x8e\x0e\x09\x92q\x98T\xaa" + + "\xa3\x0f\x0c\x03`8Z \xb0&\x9awh\xa7F\xef" + + "\xa7\xf7\xea\xa2\xa3\xf4^}\xd4\xa0\x9f\x86('\xcd\xc6" + + "(\x0b\x90\x13\x7f\xd4\xf6lg\x9c\x15\x00\xa0\xf2w$" + + "aX{\xe2\x9e\x93\xb7\xf6\xf8\xe2\xdf\x84a\x01\xee\xd9" + + "\x9fs\x8cQ\xe6\x14\xfc\xe2o\x02\xc2\x86\xb5\xc7w9" + + "\x155\xe6\x00\x16*\x7f\xc7\x0bd\xc3\xf7\x88\xf81G" + + "\x98/\xff-\xcc\xfby+Ms6 2bp\xdd" + + "w\xb8k\xe8\x9c\xca\xbf\xc1L\xdf4\xc6\x0c+C\xfd" + + "\xaf\xc3\xb9wC\x9aBK:h\x1b\x96'/\x0f\x02" + + "W\xeb\xfd3]\xad\x0f\x01$\xb3*&=j\x8eC" + + "2\x1d\xef'0\xa7br\x1f\xa5c\x95L\xc7\xc2\xde" + + "J2\x7fa\x02\x9d\xce;c\xcc\xcb;P9h}" + + "O^`r\xe86m*)\xd3\xb8\xc2\x17\xd8\xf1\x1d" + + "_\x84\xb0\x0d\x96\x98\x8c(\xad\xe58\xb4R\x1cnU" + + "1\xb9:\x10\x87v\x9a\xf2\x1d*&\xef\x9a\xcd\xecn" + + "\xe0\x00\x11gAW\xc4\xd5\x9dX\x0d\x11\xdf\xd6\x95\"" + + "\xa1\x97\xc8\x84^\xdc/\x12\xbay)@\xc4\xb2-\xee" + + "\x1bt\x96[\xcc\xa4D\xe1\x13\xe5\xbf\xc3i\xe6|\xe1" + + "\xaf+\xa9\x88\xc7<\x9e\x0ca\xe0\x9bs\x14\x97\x867" + + "\xe4\xdc\xe4\x812k\xba_\xa5\xb67G4b_\x90" + + "5\x15\x04\xad\xd9G\xf8\x91 k:\xacR[z\x88" + + "\xf0\x87\x09WQ\xd2\xa6\xe3\xeaS\x00\xa9\x87\x09\x7fB" + + "\xd0&U\xd2\xa6\xc7\x85\xfd\x13\x84\x9f\x16\xb4)$i" + + "\xd3)\x95\xda\xd2'\x09\x7fV\xd0\xa6*I\x9b~$" + + "\xec\x13\xc3\xfe" + + "\x95\xd4k\x04k\x8aH\xd6T%\xba\xfc\x10u\xe7M" + + "\x8255I\xd6\xd4(XD\x85\xad\xcd\x8dJ\xd64" + + "/\xf4\xfc$V\xa6\xa9\x925-\x09\x91\x9b\xcb\x08\xbf" + + "C\xb0\xa6\xb9\x925\xb5\x09;\xb7\x11~\xa7`M\x9a" + + "dM\x9dB\xffN\xc2\xfb\x04k\x8aI\xd6\xd4#X" + + "M\x85\x95\xcd\x9f'Y\xd3\x80\xb0\x93 \xfc^\xc1\x9a" + + "n\x92\xaci\xab`\x17[\x08\xff\x96`M\xf3%k" + + "\xda%\xd8`\x85\xad-\xfc\xa6dM\\\x8c\x9b%\xdc" + + "\x13\xac\xa9G\xb2\xa6\xfb\x85\x9d\x0a[kY+YS" + + "A\xe0\x13\x84\x1f\x12\xac\xa9W\xb2\xa6\x07\x05~\x80\xf0" + + "c\x825\xf5I\xd6tT\xf8Yfk\x18\x97\xa4\xe9" + + "\x91\xd0R\x80\xd41\x82O\x84\x14\x14\xf7\xd9\xe6\xa0\xc3" + + "!\xe2\xba\x81\xee\x95\x99\xe3\xac\xe0n\xb6\xb0\xf85h" + + "]\xb7\xf8\xc4QQ\x18v\xd8\x1e\x9e02\x10\xcez" + + "n\x19\xd5\x99\x9b\x1d\xb6\x99\x83z\xe0f\xbb\\\xd3t" + + ">\xe3X\xe5\x06^\xdcps\x1d\xa6K\x12\xb6\x95!" + + "ix\xa6\xf7\x94m\xdc)\x944\x82\xef\xef\xe7i{" + + "\x03gN\xf9\x8d\x11\xdbI\xf3^\x9b\x81\xeaze\xd0" + + "p\x07\x99\xb3\x87hAe\xe0\x1c\xcb\xbb<\xc1<\x88" + + "\xd0\xe4\xa7\xc0\xb6\x85\xa2\xfa\x19\x16C3@\x80l\xc7" + + "\xdb\xc0\x19`e<\xcfa##Fz\x00m]~" + + "#\x0a\x12\x84\x0csS\x1eK\xef\x09\x8e;j\xeb\x9c" + + "f\x01\x93&*\x0b\xdb\xa0\x03q\xfe\xb9\x8b\xd4\xd3m" + + "\x9a\xf6x0B\x95\xe5\xf0\xec\\\xca\xc8\xa0Ufq" + + "\xf2C\xcbt\xa3\x12O\xd8X\x8a'N\x95m\xe3X" + + "\x8a\xf7\x94ws\\g\xe6\x00\x9b\x80\xf8\x10\xcfpk" + + "2.\xe2\xd6\x93\xf6\x8c1^\x99\xb0\xc7]\x93\xf5\xf6" + + "\xae\x83n+\xc32\x01SEA\x1f\x1a.\x17\"\x9c" + + "&\xdb\x84\xb6\xd7\xe3\x8c\x06\x13Fd\xf3=4\xe1^" + + "'o\xb8\x81\x81D\xee\xcd(\xc9\xe5M\x97\xf7X:" + + "\xc47\x98\x86\xceKx8\x93sg\xf9\x8d{\xca\xb9" + + "|\xe7,;\xf7\xbf\xbb\x91\xfe\xf6\"+\x15\xa44\\" + + "\xc8\x89STv)\x9d\xb2-l\x1b\x12\xa7h\xab<" + + "E\x97\xf7\x8b\xb6p\xc9J\x80\xfd\xe9\xbc\xe3\x10i\xca" + + "9\\7\xd2\x1e\x07\xd4\xfd\x9c\xed\xba\xc6\xb0\xc9Kg" + + "\xab\xa5\x8b]\x10\x19a\x86y\xc3\x8b\xf0\xbe\xe2\x95k" + + "\xf9\xc6u\xca5\xf0\x1a\x80\xe4\xa3*&\x9f\x0c4\x16" + + "'\x87\x02w\xc3\x0aJ\xd7\xcf\xec\x0c\xdc\x0d\xab\x8al" + + "\xb0\xce\x1e\x04H>\xabb\xf2B\xe5\x1a\xf8<\xbd\xfd" + + "\x9c\x8a\xc9W\x02\xd7\xc0\xd7I\xf1\x9a\x8a\xc9\xf7\x14\xec" + + "f\"\xbb\xa6\xa4\xabIs\xad\xe4\x8e\xed1s\xbda" + + "\x82\xca]\xac\x01\x05k p}\xcc\xf5\xf5\x86\xc9]" + + "(K\xcc\xe2w+@\xb7tK\xdcP\xfcRP\x12" + + "a\x1f\xf7\x98a\xbaP\xb9F.\xff\xa7\x92\xe25\xf2" + + "l\x88\xc1\xa4,\xb8Q\xf0K\x9f\xd5\xfa\xba\xa5\x0f\x82" + + "\xba\x96\xd7`\x1d5w}*&\x07\x15,-\xc1\x00" + + "E;\xa1b\xf2\xde\xc0\x12l\xa5 nQ1\xf9-" + + "%0\xe5\x00\x15\x9a]\xd4\xfe?\x00\x00\xff\xff\xd6\xbd" + + "\x94\xef" func RegisterSchema(reg *schemas.Registry) { reg.Register(&schemas.Schema{ diff --git a/mapd_repo/cereal/gps.go b/mapd_repo/cereal/gps.go index 1d3b5f8005..b774c37b5d 100644 --- a/mapd_repo/cereal/gps.go +++ b/mapd_repo/cereal/gps.go @@ -1,8 +1,11 @@ package cereal import ( + "encoding/json" "log/slog" "math" + "os" + "regexp" "capnproto.org/go/capnp/v3" "pfeifer.dev/mapd/cereal/custom" @@ -15,6 +18,8 @@ const ( externalFixMaxAge = 500_000_000 // 10 Hz source: 500 ms internalFixMaxAge = 2_000_000_000 // 1 Hz source: 2 s carFixMaxAge = 2_500_000_000 // Optional CAN observation: 2.5 s + phoneFixMaxAge = 10_000_000_000 // Companion app in the background sends sparsely: 10 s + gpsModeRefresh = 1_000_000_000 // Galaxy navigation setting reread interval maxHorizontalAccuracy = 50.0 // input sanity ceiling, not road-match qualification maxClockPairSkew = 1_000_000 // an interrupted pair cannot date a source event maxClockOffsetDrift = 1_000_000 // a larger BOOTTIME/MONOTONIC step fences queued fixes @@ -39,8 +44,53 @@ const ( GpsSourceInternal GpsSourceExternal GpsSourceCar + GpsSourcePhone ) +// Galaxy navigation's GPS source setting: backup uses the phone only without +// comma or car GPS, comma never uses it, phone prefers it whenever it has a fix. +const ( + GpsModeBackup = "backup" + GpsModeComma = "comma" + GpsModePhone = "phone" +) + +var storagePrefix = regexp.MustCompile(`^[A-Za-z0-9_-]{1,64}$`) + +func navigationSettingsPath() string { + prefix := os.Getenv("OPENPILOT_PREFIX") + if prefix == "" { + return "/data/starpilot/navigation/settings.json" + } + if !storagePrefix.MatchString(prefix) { + return "" + } + return "/data/starpilot-" + prefix + "/navigation/settings.json" +} + +// ReadGpsMode returns the saved choice, or backup when it is missing or invalid. +func ReadGpsMode() string { + path := navigationSettingsPath() + if path == "" { + return GpsModeBackup + } + raw, err := os.ReadFile(path) + if err != nil || len(raw) > 1<<20 { + return GpsModeBackup + } + var settings struct { + GpsSource string `json:"gpsSource"` + } + if json.Unmarshal(raw, &settings) != nil { + return GpsModeBackup + } + switch settings.GpsSource { + case GpsModeComma, GpsModePhone: + return settings.GpsSource + } + return GpsModeBackup +} + type GpsSample struct { Location log.GpsLocationData Source GpsSource @@ -60,7 +110,12 @@ type GpsSub struct { gpsLocation Subscriber[log.GpsLocationData] gpsLocationExternal Subscriber[log.GpsLocationData] carGps *Subscriber[custom.StarPilotCarState_Gps] + phoneGps *Subscriber[custom.StarPilotCarState_Gps] car gpsCandidate + phone gpsCandidate + mode func() string + modeValue string + modeReadAt uint64 internal gpsCandidate external gpsCandidate selected GpsSource @@ -83,6 +138,8 @@ func GpsFixFreshAt(source GpsSource, fixMonoTime, now uint64) bool { return now-fixMonoTime <= externalFixMaxAge case GpsSourceCar: return now-fixMonoTime <= carFixMaxAge + case GpsSourcePhone: + return now-fixMonoTime <= phoneFixMaxAge case GpsSourceInternal: return now-fixMonoTime <= internalFixMaxAge default: @@ -134,6 +191,35 @@ func (s *GpsSub) clearCandidates() { s.internal = gpsCandidate{} s.external = gpsCandidate{} s.car = gpsCandidate{} + s.phone = gpsCandidate{} +} + +func (s *GpsSub) gpsMode(now uint64) string { + if s.modeValue == "" || now < s.modeReadAt || now-s.modeReadAt >= gpsModeRefresh { + read := s.mode + if read == nil { + read = ReadGpsMode + } + s.modeValue, s.modeReadAt = read(), now + } + return s.modeValue +} + +// updateWrapped admits a StarPilotCarState.Gps-shaped fix dated by its own source time. +func (c *gpsCandidate) updateWrapped(event DecodedEvent[custom.StarPilotCarState_Gps], sensor log.GpsLocationData_SensorSource, + clock clockSample, barrierMono, maxAge uint64) bool { + sourceTime := event.Value.SourceMonoTime() + if sourceTime == 0 || sourceTime > event.LogMonoTime || event.LogMonoTime > clock.monoAfter { + return false + } + location, err := carGpsLocation(event.Value) + if err != nil { + return false + } + location.SetSource(sensor) + valid := event.Valid && !math.IsNaN(float64(location.Speed())) && !math.IsInf(float64(location.Speed()), 0) && location.Speed() >= 0 && + !math.IsNaN(location.Altitude()) && !math.IsInf(location.Altitude(), 0) + return c.updateWithAge(DecodedEvent[log.GpsLocationData]{Value: location, Valid: valid, LogMonoTime: sourceTime}, clock, barrierMono, maxAge) } func (s *GpsSub) clockReady(clock clockSample) bool { @@ -166,7 +252,7 @@ func (s *GpsSub) ReadSample() (sample GpsSample, success bool) { clock = s.clock() } ready := s.clockReady(clock) - internalNew, externalNew, carNew := false, false, false + internalNew, externalNew, carNew, phoneNew := false, false, false, false if event, ok := s.gpsLocation.ReadEvent(); ok && ready { internalNew = s.internal.update(event, clock, s.barrierMono) } @@ -176,23 +262,29 @@ func (s *GpsSub) ReadSample() (sample GpsSample, success bool) { if s.carGps != nil { if event, ok := s.carGps.ReadEvent(); ok && ready { - sourceTime := event.Value.SourceMonoTime() - if sourceTime > 0 && sourceTime <= event.LogMonoTime && event.LogMonoTime <= clock.monoAfter { - location, err := carGpsLocation(event.Value) - if err == nil { - carNew = s.car.updateWithAge(DecodedEvent[log.GpsLocationData]{Value: location, Valid: event.Valid && !math.IsNaN(float64(location.Speed())) && !math.IsInf(float64(location.Speed()), 0) && location.Speed() >= 0 && !math.IsNaN(location.Altitude()) && !math.IsInf(location.Altitude(), 0), LogMonoTime: sourceTime}, clock, s.barrierMono, carFixMaxAge) - } - } + carNew = s.car.updateWrapped(event, log.GpsLocationData_SensorSource_car, clock, s.barrierMono, carFixMaxAge) + } + } + if s.phoneGps != nil { + if event, ok := s.phoneGps.ReadEvent(); ok && ready { + // The enum has no phone value; android is the closest. + phoneNew = s.phone.updateWrapped(event, log.GpsLocationData_SensorSource_android, clock, s.barrierMono, phoneFixMaxAge) } } + mode := s.gpsMode(clock.boot) + phoneFresh := ready && mode != GpsModeComma && GpsFixFreshAt(GpsSourcePhone, s.phone.fixMonoTime, clock.boot) source := GpsSourceNone - if ready && GpsFixFreshAt(GpsSourceExternal, s.external.fixMonoTime, clock.boot) { + if phoneFresh && mode == GpsModePhone { + source = GpsSourcePhone + } else if ready && GpsFixFreshAt(GpsSourceExternal, s.external.fixMonoTime, clock.boot) { source = GpsSourceExternal } else if ready && GpsFixFreshAt(GpsSourceInternal, s.internal.fixMonoTime, clock.boot) { source = GpsSourceInternal } else if ready && GpsFixFreshAt(GpsSourceCar, s.car.fixMonoTime, clock.boot) { source = GpsSourceCar + } else if phoneFresh { + source = GpsSourcePhone } sample.SourceChanged = source != s.selected if sample.SourceChanged { @@ -215,6 +307,10 @@ func (s *GpsSub) ReadSample() (sample GpsSample, success bool) { sample.Location = s.car.location sample.FixMonoTime = s.car.fixMonoTime sample.NewFix = carNew + case GpsSourcePhone: + sample.Location = s.phone.location + sample.FixMonoTime = s.phone.fixMonoTime + sample.NewFix = phoneNew default: return sample, false } @@ -234,24 +330,28 @@ func (s *GpsSub) Close() { if s.carGps != nil { s.carGps.Sub.Msgq.Close() } + if s.phoneGps != nil { + s.phoneGps.Sub.Msgq.Close() + } } func GetGpsSub() (gpsSub GpsSub) { return GpsSub{ - carGps: optionalCarGpsSubscriber(), + carGps: optionalWrappedGpsSubscriber("starpilotCarState", CarGpsReader), + phoneGps: optionalWrappedGpsSubscriber("starpilotNavigation", PhoneGpsReader), gpsLocation: NewSubscriber("gpsLocation", GpsLocationReader, true, ms.Settings.SubscriberSettings.ShadowGpsLocation), gpsLocationExternal: NewSubscriber("gpsLocationExternal", GpsLocationExternalReader, true, ms.Settings.SubscriberSettings.ShadowGpsLocationExternal), } } -func optionalCarGpsSubscriber() (subscriber *Subscriber[custom.StarPilotCarState_Gps]) { +func optionalWrappedGpsSubscriber(service string, reader func(log.Event) (custom.StarPilotCarState_Gps, error)) (subscriber *Subscriber[custom.StarPilotCarState_Gps]) { defer func() { if recover() != nil { subscriber = nil - slog.Warn("Optional car GPS subscriber unavailable") + slog.Warn("Optional GPS subscriber unavailable", "service", service) } }() - value := NewSubscriber("starpilotCarState", CarGpsReader, true, false) + value := NewSubscriber(service, reader, true, false) return &value } diff --git a/mapd_repo/cereal/log/log.capnp b/mapd_repo/cereal/log/log.capnp index ea3b2c2076..f595ee70c7 100644 --- a/mapd_repo/cereal/log/log.capnp +++ b/mapd_repo/cereal/log/log.capnp @@ -2623,7 +2623,7 @@ struct Event { # DO change the name of the field and struct # DON'T change the ID (e.g. @107) # DON'T change which struct it points to - customReserved0 @107 :Custom.CustomReserved0; + starpilotNavigation @107 :Custom.StarPilotCarControl; customReserved1 @108 :Custom.CustomReserved1; starpilotCarState @109 :Custom.StarPilotCarState; customReserved3 @110 :Custom.CustomReserved3; diff --git a/mapd_repo/cereal/log/log.capnp.go b/mapd_repo/cereal/log/log.capnp.go index 52bf0b81e1..c57a20682b 100644 --- a/mapd_repo/cereal/log/log.capnp.go +++ b/mapd_repo/cereal/log/log.capnp.go @@ -27463,7 +27463,7 @@ const ( Event_Which_customReservedRawData0 Event_Which = 122 Event_Which_customReservedRawData1 Event_Which = 123 Event_Which_customReservedRawData2 Event_Which = 124 - Event_Which_customReserved0 Event_Which = 105 + Event_Which_starpilotNavigation Event_Which = 105 Event_Which_customReserved1 Event_Which = 106 Event_Which_starpilotCarState Event_Which = 107 Event_Which_customReserved3 Event_Which = 108 @@ -27541,7 +27541,7 @@ const ( ) func (w Event_Which) String() string { - const s = "initDatasentinelbootcancontrolsStateselfdriveStategyroscopeaccelerometermagnetometerlightSensortemperatureSensorpandaStatesperipheralStateradarStateliveTrackssendcanliveCalibrationcarStatecarControlcarOutputlongitudinalPlandriverAssistanceubloxGnssubloxRawqcomGnssgpsLocationExternalgpsLocationliveParametersliveTorqueParametersliveDelaycameraOdometrythumbnailonroadEventscarParamsdriverMonitoringStatelivePosemodelV2drivingModelDatadriverStateV2narrowRoadCameraStatecabinCameraStatewideRoadCameraStatenarrowRoadEncodeIdxcabinEncodeIdxwideRoadEncodeIdxqNarrowRoadEncodeIdxlivestreamNarrowRoadEncodeIdxlivestreamWideRoadEncodeIdxlivestreamCabinEncodeIdxsoundPressurerawAudioDataoperatingSystemLogmanagerStateprocLogclocksdeviceStatechestnutStatelogMessageerrorLogMessagetouchuiDebuguserBookmarkbookmarkButtonlateralManeuverPlantestJoysticknarrowRoadEncodeDatacabinEncodeDatawideRoadEncodeDataqNarrowRoadEncodeDataalertDebuglivestreamNarrowRoadEncodeDatalivestreamWideRoadEncodeDatalivestreamCabinEncodeDatacustomReservedRawData0customReservedRawData1customReservedRawData2customReserved0customReserved1starpilotCarStatecustomReserved3customReserved4customReserved5customReserved6customReserved7customReserved8customReserved9customReserved10customReserved11customReserved12customReserved13customReserved14customReserved15customReserved16mapdExtendedOutmapdInmapdOutmodelaudioFeedbackDEPRECATEDliveMpcDEPRECATEDliveLongitudinalMpcDEPRECATEDliveLocationKalmanDeprecatedDEPRECATEDorbslamCorrectionDEPRECATEDliveUIDEPRECATEDsensorEventDEPRECATEDliveEventDEPRECATEDliveLocationDEPRECATEDethernetDataDEPRECATEDcellInfoDEPRECATEDwifiScanDEPRECATEDuiNavigationEventDEPRECATEDliveMapDataDEPRECATEDgpsPlannerPointsDEPRECATEDgpsPlannerPlanDEPRECATEDapplanixRawDEPRECATEDandroidGnssDEPRECATEDlidarPtsDEPRECATEDnavStatusDEPRECATEDtrafficEventsDEPRECATEDliveLocationTimingDEPRECATEDliveLocationCorrectedDEPRECATEDnavUpdateDEPRECATEDorbObservationDEPRECATEDlocationDEPRECATEDorbOdometryDEPRECATEDorbFeaturesDEPRECATEDapplanixLocationDEPRECATEDorbKeyFrameDEPRECATEDorbFeaturesSummaryDEPRECATEDfeaturesDEPRECATEDkalmanOdometryDEPRECATEDuiLayoutStateDEPRECATEDpandaStateDEPRECATEDdriverStateDEPRECATEDsensorEventsDEPRECATEDlateralPlanDEPRECATEDnavModelDEPRECATEDuiPlanDEPRECATEDliveLocationKalmanDEPRECATEDliveTracksDEPRECATEDonroadEventsDEPRECATEDgyroscope2DEPRECATEDaccelerometer2DEPRECATEDtemperatureSensor2DEPRECATEDdriverMonitoringStateDEPRECATEDgpsNMEADEPRECATEDuploaderStateDEPRECATEDnavInstructionDEPRECATEDnavRouteDEPRECATEDnavThumbnailDEPRECATEDgnssMeasurementsDEPRECATEDmapRenderStateDEPRECATED" + const s = "initDatasentinelbootcancontrolsStateselfdriveStategyroscopeaccelerometermagnetometerlightSensortemperatureSensorpandaStatesperipheralStateradarStateliveTrackssendcanliveCalibrationcarStatecarControlcarOutputlongitudinalPlandriverAssistanceubloxGnssubloxRawqcomGnssgpsLocationExternalgpsLocationliveParametersliveTorqueParametersliveDelaycameraOdometrythumbnailonroadEventscarParamsdriverMonitoringStatelivePosemodelV2drivingModelDatadriverStateV2narrowRoadCameraStatecabinCameraStatewideRoadCameraStatenarrowRoadEncodeIdxcabinEncodeIdxwideRoadEncodeIdxqNarrowRoadEncodeIdxlivestreamNarrowRoadEncodeIdxlivestreamWideRoadEncodeIdxlivestreamCabinEncodeIdxsoundPressurerawAudioDataoperatingSystemLogmanagerStateprocLogclocksdeviceStatechestnutStatelogMessageerrorLogMessagetouchuiDebuguserBookmarkbookmarkButtonlateralManeuverPlantestJoysticknarrowRoadEncodeDatacabinEncodeDatawideRoadEncodeDataqNarrowRoadEncodeDataalertDebuglivestreamNarrowRoadEncodeDatalivestreamWideRoadEncodeDatalivestreamCabinEncodeDatacustomReservedRawData0customReservedRawData1customReservedRawData2starpilotNavigationcustomReserved1starpilotCarStatecustomReserved3customReserved4customReserved5customReserved6customReserved7customReserved8customReserved9customReserved10customReserved11customReserved12customReserved13customReserved14customReserved15customReserved16mapdExtendedOutmapdInmapdOutmodelaudioFeedbackDEPRECATEDliveMpcDEPRECATEDliveLongitudinalMpcDEPRECATEDliveLocationKalmanDeprecatedDEPRECATEDorbslamCorrectionDEPRECATEDliveUIDEPRECATEDsensorEventDEPRECATEDliveEventDEPRECATEDliveLocationDEPRECATEDethernetDataDEPRECATEDcellInfoDEPRECATEDwifiScanDEPRECATEDuiNavigationEventDEPRECATEDliveMapDataDEPRECATEDgpsPlannerPointsDEPRECATEDgpsPlannerPlanDEPRECATEDapplanixRawDEPRECATEDandroidGnssDEPRECATEDlidarPtsDEPRECATEDnavStatusDEPRECATEDtrafficEventsDEPRECATEDliveLocationTimingDEPRECATEDliveLocationCorrectedDEPRECATEDnavUpdateDEPRECATEDorbObservationDEPRECATEDlocationDEPRECATEDorbOdometryDEPRECATEDorbFeaturesDEPRECATEDapplanixLocationDEPRECATEDorbKeyFrameDEPRECATEDorbFeaturesSummaryDEPRECATEDfeaturesDEPRECATEDkalmanOdometryDEPRECATEDuiLayoutStateDEPRECATEDpandaStateDEPRECATEDdriverStateDEPRECATEDsensorEventsDEPRECATEDlateralPlanDEPRECATEDnavModelDEPRECATEDuiPlanDEPRECATEDliveLocationKalmanDEPRECATEDliveTracksDEPRECATEDonroadEventsDEPRECATEDgyroscope2DEPRECATEDaccelerometer2DEPRECATEDtemperatureSensor2DEPRECATEDdriverMonitoringStateDEPRECATEDgpsNMEADEPRECATEDuploaderStateDEPRECATEDnavInstructionDEPRECATEDnavRouteDEPRECATEDnavThumbnailDEPRECATEDgnssMeasurementsDEPRECATEDmapRenderStateDEPRECATED" switch w { case Event_Which_initData: return s[0:8] @@ -27695,156 +27695,156 @@ func (w Event_Which) String() string { return s[1027:1049] case Event_Which_customReservedRawData2: return s[1049:1071] - case Event_Which_customReserved0: - return s[1071:1086] + case Event_Which_starpilotNavigation: + return s[1071:1090] case Event_Which_customReserved1: - return s[1086:1101] + return s[1090:1105] case Event_Which_starpilotCarState: - return s[1101:1118] + return s[1105:1122] case Event_Which_customReserved3: - return s[1118:1133] + return s[1122:1137] case Event_Which_customReserved4: - return s[1133:1148] + return s[1137:1152] case Event_Which_customReserved5: - return s[1148:1163] + return s[1152:1167] case Event_Which_customReserved6: - return s[1163:1178] + return s[1167:1182] case Event_Which_customReserved7: - return s[1178:1193] + return s[1182:1197] case Event_Which_customReserved8: - return s[1193:1208] + return s[1197:1212] case Event_Which_customReserved9: - return s[1208:1223] + return s[1212:1227] case Event_Which_customReserved10: - return s[1223:1239] + return s[1227:1243] case Event_Which_customReserved11: - return s[1239:1255] + return s[1243:1259] case Event_Which_customReserved12: - return s[1255:1271] + return s[1259:1275] case Event_Which_customReserved13: - return s[1271:1287] + return s[1275:1291] case Event_Which_customReserved14: - return s[1287:1303] + return s[1291:1307] case Event_Which_customReserved15: - return s[1303:1319] + return s[1307:1323] case Event_Which_customReserved16: - return s[1319:1335] + return s[1323:1339] case Event_Which_mapdExtendedOut: - return s[1335:1350] + return s[1339:1354] case Event_Which_mapdIn: - return s[1350:1356] + return s[1354:1360] case Event_Which_mapdOut: - return s[1356:1363] + return s[1360:1367] case Event_Which_model: - return s[1363:1368] + return s[1367:1372] case Event_Which_audioFeedbackDEPRECATED: - return s[1368:1391] + return s[1372:1395] case Event_Which_liveMpcDEPRECATED: - return s[1391:1408] + return s[1395:1412] case Event_Which_liveLongitudinalMpcDEPRECATED: - return s[1408:1437] + return s[1412:1441] case Event_Which_liveLocationKalmanDeprecatedDEPRECATED: - return s[1437:1475] + return s[1441:1479] case Event_Which_orbslamCorrectionDEPRECATED: - return s[1475:1502] + return s[1479:1506] case Event_Which_liveUIDEPRECATED: - return s[1502:1518] + return s[1506:1522] case Event_Which_sensorEventDEPRECATED: - return s[1518:1539] + return s[1522:1543] case Event_Which_liveEventDEPRECATED: - return s[1539:1558] + return s[1543:1562] case Event_Which_liveLocationDEPRECATED: - return s[1558:1580] + return s[1562:1584] case Event_Which_ethernetDataDEPRECATED: - return s[1580:1602] + return s[1584:1606] case Event_Which_cellInfoDEPRECATED: - return s[1602:1620] + return s[1606:1624] case Event_Which_wifiScanDEPRECATED: - return s[1620:1638] + return s[1624:1642] case Event_Which_uiNavigationEventDEPRECATED: - return s[1638:1665] + return s[1642:1669] case Event_Which_liveMapDataDEPRECATED: - return s[1665:1686] + return s[1669:1690] case Event_Which_gpsPlannerPointsDEPRECATED: - return s[1686:1712] + return s[1690:1716] case Event_Which_gpsPlannerPlanDEPRECATED: - return s[1712:1736] + return s[1716:1740] case Event_Which_applanixRawDEPRECATED: - return s[1736:1757] + return s[1740:1761] case Event_Which_androidGnssDEPRECATED: - return s[1757:1778] + return s[1761:1782] case Event_Which_lidarPtsDEPRECATED: - return s[1778:1796] + return s[1782:1800] case Event_Which_navStatusDEPRECATED: - return s[1796:1815] + return s[1800:1819] case Event_Which_trafficEventsDEPRECATED: - return s[1815:1838] + return s[1819:1842] case Event_Which_liveLocationTimingDEPRECATED: - return s[1838:1866] + return s[1842:1870] case Event_Which_liveLocationCorrectedDEPRECATED: - return s[1866:1897] + return s[1870:1901] case Event_Which_navUpdateDEPRECATED: - return s[1897:1916] + return s[1901:1920] case Event_Which_orbObservationDEPRECATED: - return s[1916:1940] + return s[1920:1944] case Event_Which_locationDEPRECATED: - return s[1940:1958] + return s[1944:1962] case Event_Which_orbOdometryDEPRECATED: - return s[1958:1979] + return s[1962:1983] case Event_Which_orbFeaturesDEPRECATED: - return s[1979:2000] + return s[1983:2004] case Event_Which_applanixLocationDEPRECATED: - return s[2000:2026] + return s[2004:2030] case Event_Which_orbKeyFrameDEPRECATED: - return s[2026:2047] + return s[2030:2051] case Event_Which_orbFeaturesSummaryDEPRECATED: - return s[2047:2075] + return s[2051:2079] case Event_Which_featuresDEPRECATED: - return s[2075:2093] + return s[2079:2097] case Event_Which_kalmanOdometryDEPRECATED: - return s[2093:2117] + return s[2097:2121] case Event_Which_uiLayoutStateDEPRECATED: - return s[2117:2140] + return s[2121:2144] case Event_Which_pandaStateDEPRECATED: - return s[2140:2160] + return s[2144:2164] case Event_Which_driverStateDEPRECATED: - return s[2160:2181] + return s[2164:2185] case Event_Which_sensorEventsDEPRECATED: - return s[2181:2203] + return s[2185:2207] case Event_Which_lateralPlanDEPRECATED: - return s[2203:2224] + return s[2207:2228] case Event_Which_navModelDEPRECATED: - return s[2224:2242] + return s[2228:2246] case Event_Which_uiPlanDEPRECATED: - return s[2242:2258] + return s[2246:2262] case Event_Which_liveLocationKalmanDEPRECATED: - return s[2258:2286] + return s[2262:2290] case Event_Which_liveTracksDEPRECATED: - return s[2286:2306] + return s[2290:2310] case Event_Which_onroadEventsDEPRECATED: - return s[2306:2328] + return s[2310:2332] case Event_Which_gyroscope2DEPRECATED: - return s[2328:2348] + return s[2332:2352] case Event_Which_accelerometer2DEPRECATED: - return s[2348:2372] + return s[2352:2376] case Event_Which_temperatureSensor2DEPRECATED: - return s[2372:2400] + return s[2376:2404] case Event_Which_driverMonitoringStateDEPRECATED: - return s[2400:2431] + return s[2404:2435] case Event_Which_gpsNMEADEPRECATED: - return s[2431:2448] + return s[2435:2452] case Event_Which_uploaderStateDEPRECATED: - return s[2448:2471] + return s[2452:2475] case Event_Which_navInstructionDEPRECATED: - return s[2471:2495] + return s[2475:2499] case Event_Which_navRouteDEPRECATED: - return s[2495:2513] + return s[2499:2517] case Event_Which_navThumbnailDEPRECATED: - return s[2513:2535] + return s[2517:2539] case Event_Which_gnssMeasurementsDEPRECATED: - return s[2535:2561] + return s[2539:2565] case Event_Which_mapRenderStateDEPRECATED: - return s[2561:2585] + return s[2565:2589] } return "Event_Which(" + strconv.FormatUint(uint64(w), 10) + ")" @@ -30280,33 +30280,33 @@ func (s Event) SetCustomReservedRawData2(v []byte) error { return capnp.Struct(s).SetData(0, v) } -func (s Event) CustomReserved0() (custom.CustomReserved0, error) { +func (s Event) StarpilotNavigation() (custom.StarPilotCarControl, error) { if capnp.Struct(s).Uint16(8) != 105 { - panic("Which() != customReserved0") + panic("Which() != starpilotNavigation") } p, err := capnp.Struct(s).Ptr(0) - return custom.CustomReserved0(p.Struct()), err + return custom.StarPilotCarControl(p.Struct()), err } -func (s Event) HasCustomReserved0() bool { +func (s Event) HasStarpilotNavigation() bool { if capnp.Struct(s).Uint16(8) != 105 { return false } return capnp.Struct(s).HasPtr(0) } -func (s Event) SetCustomReserved0(v custom.CustomReserved0) error { +func (s Event) SetStarpilotNavigation(v custom.StarPilotCarControl) error { capnp.Struct(s).SetUint16(8, 105) return capnp.Struct(s).SetPtr(0, capnp.Struct(v).ToPtr()) } -// NewCustomReserved0 sets the customReserved0 field to a newly -// allocated custom.CustomReserved0 struct, preferring placement in s's segment. -func (s Event) NewCustomReserved0() (custom.CustomReserved0, error) { +// NewStarpilotNavigation sets the starpilotNavigation field to a newly +// allocated custom.StarPilotCarControl struct, preferring placement in s's segment. +func (s Event) NewStarpilotNavigation() (custom.StarPilotCarControl, error) { capnp.Struct(s).SetUint16(8, 105) - ss, err := custom.NewCustomReserved0(capnp.Struct(s).Segment()) + ss, err := custom.NewStarPilotCarControl(capnp.Struct(s).Segment()) if err != nil { - return custom.CustomReserved0{}, err + return custom.StarPilotCarControl{}, err } err = capnp.Struct(s).SetPtr(0, capnp.Struct(ss).ToPtr()) return ss, err @@ -32870,8 +32870,8 @@ func (p Event_Future) LivestreamWideRoadEncodeData() EncodeData_Future { func (p Event_Future) LivestreamCabinEncodeData() EncodeData_Future { return EncodeData_Future{Future: p.Future.Field(0, nil)} } -func (p Event_Future) CustomReserved0() custom.CustomReserved0_Future { - return custom.CustomReserved0_Future{Future: p.Future.Field(0, nil)} +func (p Event_Future) StarpilotNavigation() custom.StarPilotCarControl_Future { + return custom.StarPilotCarControl_Future{Future: p.Future.Field(0, nil)} } func (p Event_Future) CustomReserved1() custom.CustomReserved1_Future { return custom.CustomReserved1_Future{Future: p.Future.Field(0, nil)} @@ -33066,2778 +33066,2779 @@ func (p Event_Future) MapRenderStateDEPRECATED() MapRenderState_Future { return MapRenderState_Future{Future: p.Future.Field(0, nil)} } -const schema_f3b1f17e25a4285b = "x\xda\xac\xbd\x0d|T\xd5\x99?~\x9e{g2I" + - " N\x86\x9b\x18\xa0`\x84B\x05*\x94\x17i\x94\x8a" + - "1$A\xa1\x89d2\x01\x05\xa5\xf5f\xe6$\xb90" + - "s\xefp\xef\x9d\x84\xa0\x16a\xc5\x0a\xd5V,Z\xb1" + - "\xb0\x8a+[te\x15+.X\xadb\xa5\x15+\xad" + - "\xa8Tie}Y\xadbk+\xae\xf8V\xed\xfc?" + - "\xcfs\xee\xdbL\x82\xdd\xdd\xffo\xf7S\xc9|\xcf\xb9" + - "\xe7\x9e\x97\xe7\xc6`\xc6\xbe\xc6\x07" + - "@9B5\x0fSM\xb8\xa9\xe1\xc0\xe5\xff\xfc\xfdu" + - ",\xfee\x90\xf3\xf7'sU\xe7\x0f\x85\xcfX\xb5\x1c" + - "\x01\xc6fLl2\x81\x812\xb3\xa9\x8fA~\xe9\xa7" + - "\xbf\xf9\xe3\x95G\x8f\xaec\xf1j\x80\xfc\xa5\x13\xee\x1a" + - "\xff\x9d\xe3\xbb\xfe\x9b5C\x04\x9b\xdb\xda\xf4\xa9rw" + - "S\x1fc3F7\xff\x00\x18\xe4\xc7\xdf\xf0\xf2#G" + - "\xb7\x97_\xcbbc \x7f\xec\xdf\xbe^\xb1\xbc~\xc5" + - "\x93,\\\x86\x1d>0\xf7\x01P^\x9b\x8b\x7f\x1e\x9d" + - "\x9b\xc7\xda\xefh\xd7d\x9f\xeb\xb8\xedZ\x16\x1f\x0bR" + - "\xfe\xd2\xa46\xf2\xa7\x1d+~\xebL\xc7\xa3\xf3V\x81" + - "rh\x1e\xfeyp^-V\xff\xb7\xeb\xbe5\xef\xde" + - "}?\xbd\x96\xc5\xc7C(\xbfmb\xf3\x0b\xdam\x0f" + - "\xdc\xc9\xaa\x81\xba\xfd\xe6\xfc\xb5\xd8\xed\xe3\xf3\xdfb\xf0" + - "\xca\xe2+[n\xb9m\xddw\x0b;M\xed*\x07\xbe" + - "\xf9\x8er\xf8\x9b\xf8\xd7\xa1o\xbe\xc5 \xff\xd0;\x9f" + - "6M\xd0wn`\xf1\x99\x10\xc9_s\xe7\xe8\xf9" + - "e\xbf?w\x0f\xab\x96hl\x07\xda$\x89\xc1\x8c\xa3" + - "m\xd4\x89\xdb\xef\xbd\xe2\xad!\xdfL}\x8f\xc5\xaa\x07" + - "\x8c.\xd6\xfe\xbe2\xba\xbd\x861e|{=\x83\xfc" + - "\x8c\x877\xd4\xbe\xf3\xd6\x7f~\x8f\xc5\xc7@pE\x88" + - "\x84\x16\xb6?\x00J\xa6\x1d\x9f\xd3\xdaq.\xe0\xb3\xf8" + - "7\x9fy\xaa\xf5\xfb,6A\xcaO\xdc\xf7\xd6i\xb3" + - "\xb3\xfb\xff\x84\x1d^\x9aX\x05\xca\x8a\x04\xd6\xcc$\x16" + - "`\xcd\xd4\xf4o}\x9bo\xf8\x01\x8bO\x83p\xfe\x83" + - "\xd3o\xbds\xee\xf6o\xfc\xc4Y\xba\xf5\x89w@\xd9" + - "\x9e\xc0\x99\xd8\x95x\x05g\xe2\x9e_l\xdd5*\xfa" + - "\xe2\x0f\x06\x99\xe4\x19\x07\x17\x8d\x04\xe5\xe8\"\xfc\xf3\xc8" + - "\"\x9a\xb7'.\xf8\xc5\xa3\xb3\xdf\xff\xeeF\xa4\xcf\xe1" + - "\xf9\xe3\xff\x06_\xdf\xaf\xe5\x7f\xc4\x16\x96D \x02\x17" + - "\xcc8g\xf1\xc3\xc0`\xc6\xbc\xc5Dr\xf2\xdf\xfaj" + - "'m>\xbe\x91\xc5\xc6H\xf9\xe1o\x8d{\xef\x82\xcb" + - "?}\x12\xfb|b\xc9\x12P\xca.\xc5v\xc3\x97\xfe" + - "\xaa\x8cA\xfe\xce\xce-\xb7l\x8b\xfe\xfc\x87,>\x11" + - "\"\xf9u\xef\x0d\xad92\xcb\xd8\xcb\xaah\x8e\xf7&" + - "\xef\xc4V\x0f$i\x8e\xff5\xf6\xd1\x0f\x7f\xf0\x95\xf3" + - "6a\x87\xc3\x81I\x0eS7SK@y7\x85\x7f" + - "\x1eK=&3\xc8_\xd3\xdc\xbb\xe4\xa7\x8f<\xbb\x09" + - "\xa7Y\xf2\xa7\x99\xc67O\x9b\x03\xcab\x0d\xe7n\xa1" + - "\x86\xdb\xef\xc6\x11\xa7\xdd\xf3\xc9\xd9\xdf\xbb\x99\xc5GA" + - "8?|\xee\xcbW\xdc\xf6\xe0\xb7\x0f8\xdd\x80e\xb3" + - "\x90\x8c\xcb\x96\xe1z\xdc\xf6\x1b\xd8\xb2\xe5\xe3-7#" + - "\xbf\x90\xfcuw\x18\xc0\xb2I\xa0\x84\x97\xe3\x9f\xb0\xfc" + - "W\xd8\xe9\xcd[&\xec:\xb5\xb4\xec\x16\x16\xfb\xaa\x94" + - "\x9f\x1c>~\xd5Um\xaf\xdc\x81Sq$\xfd\x00(" + - "\xc7\xd3\xd8\x85w\xd3\xdd\x0c\xf2\xf7~g_\xfeO\xfb" + - "\xc7\xdd\xc2b_\x96\xf2/|\xdc\xfa\xe4\xd8?\xbcr" + - "+Qf\x06)3\x835\xc7dp\xa1\x1f\xb9\xf1\x9f" + - "Zs\xd9Wn\xc1\x89\x90\x02\x13Q\x8a\xef\x9d\x9d\x99" + - "\x0fJ<\x83\x0b\xbd8CK\xe7-V\xbc\x1a\x86\x07" + - "\xaa\x97`\xf5w\x8d\x91\xa0|n\\\x8c\xd5\xb3\x06V" + - "\xf7^\x1d\xaf\x06\xb9\x88\x96g\x1c5G\x82\xf2\xae\x89" + - "\xad\x9f0i\x80\xe3\x17}g\xeb\xd7\xdf\xd37\xb3\xf8" + - "W@\xca\xf7\xfe\xe4\x87\x9b\xd7<\xfc\xc9\xdbb\x9a_" + - "\xb3o\x03\xe5\x13\x1b{~\xc2\xc6\xc9\xfb\xf6\xb3\x9f\xff" + - "n}b\xf8m\xc5KH]9\x94\x93@9\x9a\xc3" + - "\xb6\x8f\xe5h\xc5\x1f\xf9\xed\xbe\xbb\xad\xdb\xbb~\\\xc4" + - "\xe9\xa8\xedc\xbd\xd3A\xf9\xa4\x97\xda\xeeE\xb6x\xf9" + - "\xb1y\xfb\xd2\xf3_\xfb1\x8b\x8f\x03)\xff\x8d\x1d\x1f" + - "\\\xf8\xf2\xd4q\xbb]\x0e\xaa\xf6\xad\xc25\xcc\xf4\xe1" + - "\x0e\xdc^\xfd\xe1]\x89\xa5\x7f\xdb\xc2b\xa7A\xfe\xb2" + - "\x87\xea\xff\xf4ti\xe5[\xce\x087\xf6\xad\x05e{" + - "\x1f\xb6\xbb\x8d*\xf7\xc6\xba\xff\xbe\xef\xf1![Y\xac" + - ":0\xd9\x0cfT\xaf\x9c\x0f\xca\xc4\x95Xs\xfcJ" + - "\\\x97\xeb\xe6?\xac\xac\x1c=qk\xf1\xbaP\xbb\xe7" + - "\xac,\x07e\x1e\xd5n^\x89$\xf7\xd9\xfc\xc7\xd7N" + - "N\\\xbcU\xb0\x81?\xddt\xd7\xa4\xfbv\xbft\x97" + - "C\xceo\xae\\\x06\xca'+\x89\xa6V^\x8csQ" + - "\xda\xb5\xe3Og\x9bK\xb7\xb2\xd8i\x92\xdfg\xdcs" + - "\xab\xe6\x83\xb2t\x156\xbcx\xd5\xafP>\xdc;\xe2" + - "\xdd\xbb~\xfb\xdb;pE\xa0hE\xf6\xafZ\x05\xca" + - "\x11\xaa|x\x15\xceZ\xe7\xb9#\x94C/?{\x07" + - "\x8b\x8d\x0bL\x1a\x83\x19\xb3\xafX\x0bJ\xfc\x0a\xac\xd9" + - "z\x05\x8e\xce#\xde\xa2\xd1\xc9\xd8\xaev\xc5\x12P\xae" + - "\xba\x02\xc9\xe8\xc8\x15\x0bp\xfb\xcd\x1b\xbf\xea\xa6\xec\xb5" + - "S\xb6\x15\xad\x1d\x0dO\xd1V?\xa7\xe4V\xe3\x83+" + - "V\xd3J\x7fi\xc7\xa7-\x93\x8e^\xb2\xad\xa8q\xea" + - "sx\xcdXP\xaa\xd7\x10+]\x833\xe7\x89\x99B" + - "\xce\xd5\x0c\x91r(\x99\xb1{\xcd$P\xf6\xaf9\x03" + - "\xe9o\x0dq\xba\x91\xf2G\x0f\x9d\xf6\xc7\x97\xee\xa4\xa9" + - ";[?\xd1\xf4\xdcZ\xf9\xaf8\xc67\xafY\x02\xca" + - "'\xd7\x10\x0d]\x83{\xf0\xf8\xd5\x9b\xef\xbd\xee\x9d7" + - "\xeeD.'\xf9\x1b\x87\xba1q\xdd=\xa04\xac\xa3" + - "=\xb6NH\x9eq\x9f}\xf5\xd1\x89g\xdd\x85\xc2/" + - "\xd0+\xb1\xde\xea\xb5\xab@\xc9]\x8bm\xaf\xb8\x16g" + - "\xfa\xc89w=\xbe\xfe\xd4\x83w!}B\xfe>\xe9" + - "\xda\xd5\x0f\x9c\xbav\x9fS{\xff\xb5\xf3A9B\xb5" + - "\x0f_\x8bc\xf4\xe8!^\x0d\xd1\xc0\xf4\x0d\xc1\xda\xeb" + - "\xbe[\x0e\xca\xcd\xdf\xedfl\xc6\xf1\xef\xde\x17a\x90" + - "\x7fs\xe7\x9e\xba?\xac\xf8\xe3]l0\xf1z\xfc\xc6" + - "O\x95\xcfo\xc4\xbf>\xb9\x11{r\xca;\xfa\xfc\xd2" + - "\xa3\xaflg\xb1\x11\x90\xbf\xe5\xa1\xf3\x86\xbf~\xee\xae" + - "\x8f\x91\x83U\x82\xb2x\xe3\xa7\x0a\xdf\x88u\xd5\x8dX" + - "\xf7\xf9\x1fU4}\xd8^\xf5\xaf\x83\x09\xb6G7\xbe" + - "\xaf\x1c\xd8\x88\x82\xed\xf0F\xdc)\x93\x7f|\xdd\xfb\xef" + - "\xcd\x9d\xf5\xaf\x83\xcd^\xd9M\xf7\x802\xe6&|l" + - "\xf4M\xc8\x0a<\xf9\x14\xaf\x05\xc9\xd7i\x04\x1f\xfd\xfc" + - "\xa6\x0d\xa0T\xff\x10\xd7p\xda\x0f\x89\xfc=Q\x1d\xaf" + - "\x86\xf2@G\xa8\xf1\xcd\x9b$P\xb6oB\xea;\xbe" + - ")\x82\xf3\xf1\xc2\xa8\x7f}\xee\xc8\x05\xd3\xef!\x09\xe4" + - "\xf1~\x063^\xdb\xb2\x01\x94O\xb6\xd0\x92oA\xb2" + - "V\xaf4\x1e\xbf\xf9\xea\xad;\xb1\xd3\xa1\xe2No}" + - "\x1a\x94\xf1[I'\xd8J\xeaQW\xd5\x9c\x87\xcf\x9a" + - "\xdf\xfd\xef\xc5\xcc@\x99v\xfb\xeb\xca\xec\xdb\xb1\xd9s" + - "n\xc7\xf5\xfb\xceG\x1dOT\xae\x88\xdeG\x1d\xf0\x16" + - "\x93\xc1\x8c\xed\xb7\xaf\x02e/\xd5\xdc};\xd2\\I" + - "UO\xfd\x15g\xaf\xbb\xafh\x86q[)o\xde\xfe" + - "\x8er\xfc\xf6:\xc6\x94\xea;\xb0UO\x85,\xe2\xcd" + - "\x82\x7f\xde1\x1d\x94\xd7\xee@\xaa\x98\xb7\x8d8\xff\x84" + - "\xcc?\x1fW\x16\xed\xb9\x9f\xc5G\xc3P\xffEb\xcb" + - "\x1e\xf9\x97I\xa0\x1c\xfb\x17\xe26\xff\xd2\x1db\x90\x7f" + - "\xe6/\xd2\xeb\x93\xb6<\xb7\x8b\xc5\xbf\x0a\x01a\xe5p" + - "\xd0];\x1e@\x0e\xbao\x07\x92Evz\xf7\xc85" + - "W\xffm\x17J\xc1\xd2\x80\xd6L\xd36\xed\xeee\xa0" + - "4\xdf\x8d\x7f6\xdc\xbd:\xcc \x7f\xfa\xc6\xc83\x89" + - "\x9fL{\x80\xf4\xe0\xf4w\x87=|\xde\xa5C^\xc5" + - "\xd9Xw\xdf;\xa0l\xbb\x8f\x14\xd7\xfbV3\xc8\xef" + - "\xfd\xd1\xa8\xdd\xdf\xba\xf5\xd9\x07Xl\xa2\x94\xffe\xe2" + - "\x94\xbd\x95\x0f\x8e\xf8\x04k\x1e\xba\xef\x01P\x8eQ\xcd" + - "7\xa9fs\xf9\xeb\xe9\x91\xf3\xff\xfc\xd3\xe2\xfdD\x04" + - "4\xe6\xfee\xa0\xcc\xbc\x1fkO\xbb\x1fg\xcecm" + - "\x83q\xafC\xf7\x8f\x05\xe5\xb5\xfb/@\xa5yW\x0d" + - "r\xaf\xe7?*\x1f\x96\xfa\xcd\xb7\x1f\x1a\x8c\x95+K" + - "\x1f\xfcT\xd1\x1eD\xba\xcf=\x88\xa4\xdc\xb5\xe5\xd9\x9e" + - "\xed\xe5\xfaC\xc4C\xbd\x8e0\x98\xb1p\xf7m\xa0d" + - "v\x13\xc7\xdb]\x87:\x89\xabD\xc6\xab!\x12h\x96" + - "\xfa\x9c\xd9}\x0f(\xeb\xb0\xf6\x8c5\xbb?\xc2^l" + - "-]\xae\xfe\xf6o\xe5{q\xfd<\x05\xda\xd1\xad\x8f" + - "\xee\x9d\x83\xcb\xf1\xe6^\xdcy\xc3\xfa\xce\x1b\xd7\xff\xbb" + - "y{\x8b\xb4\xb3\xea\x12\xaa\x1a~\x18\xad\x87\x19\xb1\x87" + - "\xbf6\x84\x81\xafc\xc5O\x87\x88/\x91\x85\xbe\xfc\xcb" + - "\xf9\xa0\xec\xfd%\xfe\xb9\xfb\x97?A\x12\xba\xe3\xfb\xeb" + - "\xcfx'u\xfd^\xa1Ey\x84L\xb5\x97\x1e0A" + - "Yq\x804\xd0\x03H\x15\xd7]\xd9\x10\xfd\xf5\xae_" + - "\xecE\xe3H\xce?\xfa\xe9e\x0f\xfetY\xea\x90K" + - "@\x07\x0e\xdc\x83=>r\x00\xd7c\xe8\xf7\xcf\xbe5" + - "\xb6q\xff^\xdc\xfe\xc3\xfc\xedO\xed\xae\x7fz-(" + - "[\x9f\xa6\x9d\xfd4m\xe7\x9b\xfa\xd5\xa1\xcf\xcc\xb8\xef" + - "a\xecEY\xfe\xb4\xddoO\xfa\xfe\xb4c\xaf\xb1\xea" + - "2j\xf8\xc4\xa1N\x1c\x1f" + - "\xfe\xd2\x9d\xa0\x94\x1d\xc1\xda\xe1#X\xfb\xa3\x13_\x7f" + - "\xf3\xdf\x9f\x9b\xfa\x98\xd0)=\xe1^]M\xc3{\xf4" + - "\xc8|\xd2\x82\x8f\x90\xd0y\xfe\x99\x8b\xf7\xfd\xf3\xf8\x9d" + - "\x8fS\x87=\xdb\x07\x87\xff\x87\xe9\xa0\xc4\xfe\x80\xadV" + - "\xfc\x01\xf5\x80\xfc?M?\xf4`\xdb\x1f\x1eg\xb1)" + - "R\xfe\xb2\x17\x86\xfei\xf2\x8f\x9e\xfb\x98X\xd0\x1f~" + - "\x0f\xca>\xaa\xf9(\xd5\xf4hv0\xb62\xfb\xe5\xb1" + - "\xa0\xb4\xbe\x8c\x9bc\xdd\xcb$O\x13\x97\xb6\xfe\xdb\x84" + - "\xd8yO\x90I\xb2c\xc9\x19U\xbb\xbe~?\x99$" + - "G_\xf9\x14\x94O^!\xe6\xfa\x0a\xee\xd1\xd6\x07K" + - "\xcc\xddw\xb6\x0aYZ\xf7\xf99\xb0" + - "\x04\xc7P6\x0bH\xc5J^h]\xf6~\x7f\xfey" + - "\x16\x1b/\xe5O9\xbcs\xf1\x85\xeds\x8f!Al" + - "=\x17n\x82\x9a\xdd\xe7\xd2\xf4\xec:\x17>b\x90o" + - "l{\xd7\x9c\xf1\xb7\x95\x87Y\xac:T@\x98\x0d\xb3" + - "q\xee[gc\xe5\x8b/\x9c\x0d2\\\xdc\x81\x10c" + - "\xf9?-\xf8\xb7\x8f\x16N~\xe80\x8bM\x80|\xe2" + - "\x8c+o\xf9\xf5\x0d\xe1#N\xff\x9bg\xc3\x9dP\xb3" + - "\x94\x1e\xabY<\x9b\x96`\xf3U\xe3F\xce~\xfd\xa6" + - "\xdf\x0d \xfe\xc3\xb3q\xbd\x8e\x89\xcao\xce&\x0a\xfd" + - "\xd3\xea\xdf<;\xf2\xba[\x7fW\xec\x8a*\xc3\xd6\xe1" + - "<\xe8\x84\x9a\xea\xf3hvb\xe7\x01\xf1\xa4\xbf\xfcd" + - "\xe7\xa7\x0f\x0d\x1b\xf9\"\xd9R\xde\xaeeP7\xba\x01" + - "7\xe2\xb4\x06j~r\x03\xe0\x1e\xdf\xf2\xbb\xa5\xd9\xb7" + - "vU\xbeD\xbb\xc5\xa3\x06\x06u74\xc0\x12\xa8\xd9" + - "&*om\xa0\x8dx\xd9\xc7\xc3\xd7\xac\xbc\xbe\xe1%" + - "\xa4\x9d\xb1E<\xbdn_\x03\xcc\x87\x9a\xc3\xf4@\xdd" + - "\xa1\x060\xcaX`6\x06\xd1\xa6\xeaN|\x137d" + - "\xb8\x05\xe9\xbf.\xd6\x02\xa4\xe1\x1e[\xb2V\xb9\xe5\xf6" + - "\x1f\xfe\x9e\xc5\xa7@\xd8go\xce\xda\x1eo\x83\xa7\x81" + - "AM8N\xbd\xf7\x9c\xbb\xc4\xd9=Q&\xc8\xf3@" + - "\x1c\xc9\xf3h\x9c\xb6\xd7\xb18 \x13V\xef=\xf4\xdc" + - "-\xdf{\xf3\x0f\xc5\xb6t\xdd\xf1v\xb8\x0dj\xca\x12" + - "\x829$\x00E\xe3\x97/7o\\\xaf\x8c{y0" + - "\xe60/\x01#\xa1f\xb1\xa8\xbf0A\x8d+\xe7\x9d" + - "\xael\xb8~\xea\xd1bE\xa5n|\x07l\x80\x9a\xd9" + - "\x1dT\xf9\x9c\x0ej\xfc\xb4\xb9\xcb\xff\xe3\x9c\xe5_\xf9" + - "\xcf\xc1|8u+:\xb0\xf55\xf4@\xddU\x1d@" + - "R\xcf[\xca\x01;+\x0c\xa1\x9a\x89\x8b\xe0\xfd\x9a\x99" + - "\x8b\xa0\x8f\xb1\xba\xdd\x8b\xc4>\xf1\xd4\xf8x5\x0c)" + - "R\x1a\xeaF\\\x02\xd3\xa1f\xe2%4\xfb\xe7\\\x02" + - "\xa4T{\xbb\xaf\x90\xbd\x89\xf5\xdav)\xbc\x035\x8f" + - "^\x0ag\xe0\xe6\xbfT\xec\xf7\xbfo\xe9\xdf\xa8\x8d\xfd" + - "\xa7W\x91>K|\xfa\xac\x8e\xd1z\x1dX\x0a\xa8\xf8" + - "\xd5\x1c^J3\xd4\x96\x1e=\xab\xb5\xfc\xfdWY\xfc" + - "k\x100\xce\x85\xbe\\\xb7\xef[\xf0\x1cU\xfe\x16\xb1" + - "BO\x87\x8cWCY\xa0\xf7D\xf9'\xbe\x05\xe5P" + - "\x13\xfe\xb6\xa0\x9do\x8b\xde\x7f\xed\xe5\x89\xb9\xdf\xec\x89" + - "\xfc\x17\x8b\x7f\x03\x85a\xef\xbd\xd7^\xb5\xed\xaew\x1c" + - "\xe5\xb6nk'L\x97\x18\xd4\xec\xee\xa4\xe6_\xaf>" + - "\xe3\xfb\x1c\xc6\xbdQ\xc4\x99q\xa45G:\xe1\xfd\x9a" + - "7;i\xbd^\xeb\xa4M[q\xc3\x07\x1f\xbd}\xee" + - "\x8f\xdf .\xe29\x12\x18\xd4-M\"\x17\xc9%\xc5" + - "\xc2%\xe1\x0c\x9c\x95o\xbc\xfd\xf4\x97N\x01xS\x10" + - "f\x81\xe8\xac\x1b\x9f\xc2mxN\x8a\x1e\x98\x99\x82o" + - "\x97\xa0\xfa|j\xd9\x90?\xddx\xea\x1f\x8bU\x1a\xaa" + - "tb9\x98PS\x96\xa6\x1f\xe1\xb4\x18\xec\xce\xf7^" + - "\xb9\xcc|\xdb\xfa\xa3x\x85\xef\"#\xda\xdfl\xe0\xd6" + - "\xba\xdb\xa0\x11l7h\xf2\xbd*E\xa2\xa5\x1a\xeb\xac" + - "\xcf\xc2\xfb57g\xa1\x8e\xb1\xba\xfdY 5}\xfd" + - "Y\xd7\x7f\xdf~h\xec[,>\x15\x86\xf9\xe6\x00i" + - ",u;{\xe1\xf7\xb8X\xfbziz\xeeZ\xff\xe1" + - "\xaf\xdb\xee\xb0\xdfB=\xa4\xa4\xd0F\xaf\x1b\xdd\x07\x0f" + - "@\xcd\xcc>\xea\xfe\xb4> M\xe4\xd1\xad?\xdd3" + - "\xb7b\xc8\xdb\xc5\xf4O\x94\xd6\xb0\x0a\x19\xe1\xc2UB" + - "\x8a\xad\x12\xf4\x7f\xec\x9f\xd2\x15\xb7\xad=\xed\xed\x01|" + - "\xed\xe8\x15\xb8\xbdN\\A\x83=~\x85\xe0\xe3\xff\xfc" + - "\xe2o\xa4\xdfl}[(f\x9e\xc1A\xfdYw%" + - "\xd6\xdfz%\xb5\xbe\xf9J\xd1\xfa\x03\x9b\x1f\x90v\xfc" + - "\xf4\xafo\xa3\x14\x0a8\xea\xe9\x81\x99\xdf\x81N\xa9f" + - "\xf1w\xc4f\xff\x0e\xcd\xa6\xa7<\x15\xcd&=\xd0\xbc" + - "\x1a\xf7\xd6\xc2\xd54\x9dkV\x8b\x9d\xe2\x89\x9ex5" + - "\x94\x16/\xf1\xe25\xa8lhk\x88\x9esk\x80\x1c" + - "t\xa9o\xdf\xaao\xdd\xfb\xbdc\x03\xb8\xd5\xf8uH" + - "\x10\xe7\xac\xa3\x0e\xcd\\\x87\xcc\xf9\xf3\xfd\xbf\x98\xf6|" + - "\xfd\xdec\xf1\x890\xd6g\xd4\xe2$\xa4n\xf1:@" + - "M\xb4F[\x87\xa4\xff\xca\xe4\x87\xfe\xb8\xf7\xa9?\x1e" + - "+nu\xfd:\x9c\x97m\xd4j\xdd\xd6u@G," + - "\x9eL\x88W\xc3\xd0\"\xcd\xbcf\xe1\xb5\xf0i\x8dz" + - "-u:s-\x90E\xcc\xbf\xf4\x1f\xcbn9\xeb\xc7" + - "\xef\xb0\xf8H\x08\xf8\x18\xab\xc3\xd4\x93\xc3\x1b`\x12\xf6" + - "\xe4\xe8\x06\"\x1bo\x8f\xc6\xbf\x02a\xdf\xa0\x10D\xdc" + - "\xf0=\xf8=\xd4,\xfd\x9e\x98\xa0\xef\x09i\xee\x193" + - "\x85N)\x9a\xf6Go@\xaa?x\x031\xa8\xe37" + - "\x08&\xe8YvE\x0e\xed(\xbd\xe2\x07\xf8D\xfc\x07" + - "\xf4\x84\xf6\x03\xf8+\xda\x0bS\xa7d7=q|\xd8" + - "\xbb\x83\x98\x00u\xd3nA)\xd7|\x8b\xd0\xf1n!" + - "N\xd2\xf4\xe9\x827\xd4\xbc\xf9\x17TG\xca}\x05\xb5" + - ":D#\xd6n\x11\xeaH\xee\x16 \x13\xea\xa6}o" + - "\x1exi\xef\xf6\xbf\x14\xbb\"\xea\xb6\xde\x8a\x8b\xba\xeb" + - "Vjz\xe7\xad\xf0#\x06\xbe+t`Wj>\xbf" + - "\x15\xde\xaf)\xdbL\xe2\xadz3M\xe7\xfa\x9d\xdf\xf9" + - "\xcei\x9f\x9d\xf2W\xe1\xde\xf3\xe4\x97\xd8\xb1+6\x83" + - "\x89S\x7f\xd5f\xea\xf5\x96\xe6\xc7\xae\x7fe\xcd\xf7\xde" + - "c\xf1\xe90\xd4?c\x15\xe4x\xf7f\xb8\x07j\xf6" + - "m\xa6\x1f\x8fn\x86z4\xf1\xcf8\xf3go-Y" + - "<\xf48\xf2\x83\xd2\xfcM\xd7^\xb1\xfc\xa5\x17\xaf>" + - "\xe1<1\xf9N\x14\xa0\xcdw\xd2\x8f\x86;\xe1?p" + - "&\xbf\xfb\xea\x99\x8f\xed\x7fj\xfdq\x16\x1f\x0da\xdf" + - "\xbbE3y|\x07\xee\x11\xb8[(\xb3;\xc4\x1e\x19" + - "s\xc6\xea\x97\x96Lkx\x1f\xe9a\x88/\xbf\x1c\xe9" + - "\xbf\xef\x1e\xd8\x80Sy\xe8\x1e\xb1P\xff\x95\xfb\xe1\xab" + - "\x07\x96^\xff\xbe0~\x0a\x99\xce\x9a]\xd8\x9f\xcd\xbb" + - "\xa8\xf9\x9bw\x09\xe2Y\xd2\x7f\xdaO\x8f\xae\xb8\xeb}" + - "\x14VQ_DW\x0f\xa1\xe6\xdf\xfd)\x09\xab\xbaO" + - "~\x0a_C\xfe\xf7\xb3\x9d\x07\xca\xbf7\xe4\xf3\xf7\x07" + - "\xd8\x1d\x1b\xf7\xa0\xda\xb5}\x0f\xad\xd4\xb6=\xa4\xa7]" + - "\xbe\xe7\xb1\x1d\x7f\\>\xe1\xbf\xb1\xe7r\xa1\xef\xa1\xee" + - "\xd1=\xc8\x00\x0f\xef\x11\xaa\xd1\x1eA\x97\x9f\x1d\xd6\xbf" + - "7\xf4\xdb\xdf\xfe\xef\xc1,\x891\x0fC\xb9T\xd3\xf0" + - "\xb0\xb0\x82\x1e&]g\xc2e\xc7\x0e=\xf9\x97\xdb\xff" + - "\x9b\xc5'@\xc4W\xac\x9c\x1d~\xeca\xb8\x0d\x17\xf7" + - "\x93\x87\x89\x10\xbc\xc5\x89\x9f\x06\xa1\xa2#\xf3\xba\xc5?" + - "C\x01\x94\xf9\x99\xe05?\x13Z\xe3\xa2k\xbbG?" + - "\xfc\xe1\xba\x13\x83\x88\xc3\xbai?G\xddw\xf6\xcf\x85" + - "\xfe\xf2sz\xc3ck\x1e\x7f\xfb\xd0y\xb7}8`" + - "r\xb6\xfe\x9c\xc8XT\xde\xf9s\x9a\x9c\x0f7\xff\xeb" + - "-3~\xfc_\x1f\x16\xbb\x0d\xea\xf6\xff\x1cg\xe6\xa8" + - "\xa8|\xe4\xe7\xa4ez\xee\xeeb\x93\xa9\x12j\xc2\x8f" + - "\xc1\xd35\xb1\xc7\x88\xe6G<\x06\xf5\x8c\xd5\xe4\x1e\x83" + - "\x1a\xdfw\x12?\x1dJ\xfd\xee\xd0d\xaex\x0c;\xb4" + - "\x8e\x1e\xaa\xdb\xf8\x18\x90O\xc0\xf3[\x0e\xc2F\xf6\xee" + - "\xc7=~p?=pd\xbf\x90\x0f_}\xe9\x99\x19" + - "\xdf\x9du\xe0\x131\xa3\x9e\xaaI\x0fd~\x85\xe2j" + - "\xcd\xaf\x84\xba\xf6+\xf1\xc0-#_\xb8}\xf9\xc4\xdb" + - ">\x1d\xec\x08\xb0.|\x00\xc6BM\xf5\x01\xa1\xb8\x1f" + - "\x10\xd4\xb9\xe0\xba\xee)\xd9\xc7\xcf\xfb[Q\x18\x00\xbd" + - "\xe2\xc4\xafq\xb7\x84\x9f\x11F\xf43$\x82\x1e\xba\xe7" + - "\xf2\xf8\xef\xce\xde\xf37\x16\x9f\x06\x01o=\xd5\x1fq" + - "\x10$\xa9f\xe6A\xaa?\xed\xa0`\xb6\xaew\xa0H" + - "\xe4\x12\xb3\xbd\xf9 \xaa\x9c\xdb\x0f\xd2\xa0w\x1d\x14\xdb" + - "q\xdf\x19\xe7|\xeb\xfe\x1f\x0f\xfd\xac\xf8\xcc\x82\x94\xa4" + - "5\xbf\x85\xd7kn\xf8-\xbda\xfdo\x89F\xc7/" + - "\x1d\xb2\xa5o\xdf\xe2\xcf\x8a\x8fR\xebf>\x8b\xa6q" + - "\xfcY\xaa\xdc\xfa,\xd41\xc8\xbfP\xff\xbd\xf76}" + - "\xbb\xecsd\x0e\xa5E\xcca\xe1\xb3\xa8\xdeq\xaa_" + - "\xa7>+z\xf3\xcb1\xd9K\xbb\xaf|\xfas\x9a\x1f" + - "O;\x14$:\xf99\\\x82\x86\xe7\xc4\x8ey\x8e\xc6" + - "\xdb\xf6\xe3\x1b\xde\xd8\xba\xec\xac\xbf\x17\x12\x12\xb5\x7f\xe0" + - "94\xbd\x8f`u9\xff\xdbw>5\xd6\xef\x9c\xf9" + - "\xf7\xc1\x98\xec\xee\xe7\xe0\x9d\x9a}\xa2\xd9GE\xb3\x8b" + - "\xf9\x1b\xe3\xee\x8e\x7f\xe3\xef\xc5\xbe\xb5\xba1\xcf\xa3\xbc" + - "\x9a\xfd\xbc\xd8&\xcf\x13\xe5\xe7\x8er\xf3\xd7\x1f\xfc\xcb" + - "\xdf\x85Z\xe1\xa9\xd7\xd4\x89\xf8\xf3\xb0L\xaa\xc9\x89\xfa" + - "+\x9e\x87\xfbX>\xf0\xff\xb7\xe7\x93\xdc\xe4j\xfak" + - "\xe9\xb0\xd1\xfd\xb5\xb4\xd1=%\xa9f\xf5\xec\xacx\xd2" + - "\xc8\\\xa0[\xd6\x94&\xb3\x95\xabV\xce\xe4\x19\xae\xdb" + - "\xed\xb5\xba;" + - "k]\xcc\xf9ro\x12\xba\xb3\xe2\x19p_\xe0\x0d\x10" + - "\xdb\xc7VY-\xb6k\x05\xf1F\x9c\x11\x09K\xfdQ" + - "\xf4\xb7\xc2\xc0:\xac>a\xe4\xcc$\xf7\x07\x986\xb0" + - "\xbb\x8d\x80\xa5X&\x0f,\\\xcc\"\\5\x8b\xd1&" + - "&\xab\xfd~\xb7\x05\xd8\x0a\xeex#8\xd5\xde\xebE" + - "i\x078\xb3\x12\x984\xe7\xfd\x12\xbe?8\x80\xe0$" + - "\x89\x15\x9fkrX\x91\xe3z\xb2\x7f\x8e&\xab\xd6\x80" + - "BI\x14\x16\xac\xa3[\xa7\xcb\xe4T\x0a\xfdb\xfc\xcc" + - "'I1\x1fQ\xdf\xd7\xc6\x00\xa2\x0cd\xab\x17Na" + - "\xd0&\x03T\xfal\x98\x01\x82'a\xe7-Z/o" + - "3,>e\xae\x96\xb6\xb9\x99\xb0U\x9bOY\xd0i" + - "q\xb3\xb7V\xb55Co\x03\x88\x0fu9x\xacy" + - "\x12c\xf1\xf3e\x88\xb7H\xe0p\xef\xd8\xbc\xe9\x8c\xc5" + - "\x9bd\x88_\x8e\xbc\x1b\x88w\xc7\x96\"x\x89\x0cq" + - "[\x82\xe8rMOA\x88I\x10bP\xdb\xab\xa6s" + - "\xdc\xed&\x8e\xf5\x14\x06\xb5\xdc4\x0d\xb3\x08c\xd3\xda}\x8d-6\xed&\xdfd\x8f\xcd" + - "l\xf7\x0f\xcfb3\xe7\xfb*\x06\xfe\xf0\xf4V\xac\xe6" + - "\xb9db37\xe4\x13\xaaP\x02\x18\xd8ywy\xc0" + - "\xd7\x0c\xf2\xcd\xd9\x1e\x9e\xe1\xa6\xc6\xc0\xca\xcf3t\xa3" + - "I\xb5U\xc6X\xfe\xc2>\x9c\xaf\x9cU\xf07L\xcf" + - "_ f\xba\x19\x9c\xe7,\xc6\xe2\xa3\xe4\xd0\xd0|\x9e" + - "\x08q\xf7M\x8c\xc5\xf7\xc8\x10\x7fR\x82\x0a\xf8{^" + - "\x90\xe2\xbev\xc6\xe2\x8f\xcb\x10\x7fF\x82\x0a\xe9\xf3\xbc" + - "\x98\xf1\x03\xf3\x19\x8b?%C\xfc\x05\x09*\xe4\xcf\xf2" + - "\xa4E\xc4\x0e!\xfa\xac\x0c\xf1\x97%\xa8\x08\xfd-/" + - "\x16\xe2\x08\xb6\xf0\x92\x0c\xf17$\xa8\x08\x7f\x9a'\x0d" + - "\"\xf6\x1a\xae\xd9\x1b2\xc4\xdf\x93\xa0\xa2\xe4\x93<\xe9" + - "\x0f\xb1w\xb1\xee\x9fe\x88\x7f,A>3p\xccP" + - "\xe9\xcf1\x03\xa8d\x90\xe7\xfe,@\xa5?\xe9N\xa9" + - "\xe6\xcf\x0bT\xfa\xab\xe0\x94\xf6\xf83\x05\x95A\xcd\xaf" + - "\xb0\x14\xa6Ce0.\x82J\xbb\x07\xce&T\xfa\x0b" + - "\xe8\xd4\xb2\xfc5\x84J\x9fX\x9c\xd2\xc1\xb7c\xab\x91" + - "\xe2i\xec\xf4\xa2\xe9S\x9a4\x8b\xeb\xddj7o3" + - "yJK\xd6\"\xfdZ\xb8\x1d\xc7y\x0c\xe4\xdda\x8c" + - "\xc5\xdfF9\x0d\x01\x05\x10\x00\xf5\x86\x10\xa0\x86\x06\x01" + - "\x0dp4\xdc\xc4X\xe2t\xc4\xcfE\\\x96\x85\x06x" + - "\x0e\xa0~p.\xe2\x97 \x1e\x0a\xd1\xea\xcdX\x08\xc3" + - "P\xb1\xba\x1c\x0b\xae\xc4\x82p\x98\x16pF\xbf(\xb8" + - "\x06\x0b\xee\xc0\x82\x92\x12Z\xc3\x19[E\xc1\x0e,x" + - "\x12\x0b\"\x11\xa1\x04\xee\x03T\xad\x1eG\xfce\xc4K" + - "K\x85\x12x\x04P\xd5x\x09\xf1\x0f@\x02\xb0\x8b\xb9" + - "V\xa7\xa9.\xe7M\x9a\x05\xeeTD\x8cN\xab\xb8R" + - "\xb7j\xd1d\x81\xa8bt\xc2\x80*\x96\xcd\xb9\xb9\xa0" + - "\x97\x83ij)\xac#\x0fl\x86\xde5\xa3\x95\xcb6" + - "7\xad6n&H\xfe&V\xe4T\x93\xa7\x06o\x96" + - "\x1e9\xeb\x7f\xff\xc8\xcc\xff\xd5#\xdd\xaa\xd5fr\xcb" + - "b\xb5X>x\x8bm&\x07\xcb\xa2rv2\xd6_" + - "\xc8_[U]\xedv\x85T\x9bi$\xb9Uo\xd1" + - "/$\xb2*\x8f\xc8\xaeB)\xb5R\x86\xf85\xbe\x94" + - "Z3\x96\xb1\xf8\x952\xc4\xafC\xfa:]p\x86u" + - "s\x18\x8b_-C\xfcz$\"a^\xc4\xd6#c" + - "\xb8N\x86\xf8&\xa4\xb81\x82/l\\\xcbX\xfcF" + - "\x19\xe2[$\x88\xeaj\x86\xc3P&\xc1P\x06\x91\xac" + - "\xe6\xc9\xb6\xd5fN\xd75\xbd\xdbU\x02\xf3|\xa5f" + - "7\x1a)\x8e[\xd6\xa9\x93\xb7z\x8c\\:5\x87C" + - "\xbb\xa8\xcc\xbc\xda\x83o\xb0\x04\xd7-\xc3l\xee\xe5\xba" + - "\x8d\xdbL\x88\x15\x92*,^\xe9\x0dY\xc5\x91\\&" + - "C\xbc\xc7\xdfV1>\x8b\xb1\xf8\xe52\xc4\xd3\xfe\x9e" + - "\x8ai89)\x19\xe2Y\x1c\xde\xe3d\xaa\xc42\xcb" + - "\x18\x8b\xa7e\x88\xaf\x94`u/7-\xcd\xd0\xdd\x1e" + - "\xd7[\xd4\x03\xf7g\xd4\xee\xcfro49=\xa9\xa6" + - "\xb5N\x93E\xb1G\x03\x86R(\x8d\x1aU=\x8ac" + - "\xc0\xd5\x1a\xbc\xeb C \xa8)\xc6\x97`{\xa2\xdf" + - "q\\\xc0\x16\x19\xe2\x97\xe0`J\xc4Z-D\xb0M" + - "\x86\xf8e\x12\xacVS)\xa49O\x83sg\x8a\xc9" + - "<\x15I\xa96T0\x09*\x18D,3\xe9i\x86" + - "\x83\xf7\xb4\xc3\xc8\xc9\xc9\x9e\"\xaa\x1a\xebS\x957\xc5" + - "k&\x05\xc9\xaa\xd2!\xabI\x01\xb2\x92\xc3\x0eY!" + - "x\x8d\x0c\xf1\x1b\x91\xd6J\x04Y\xdd0\xdd\xa7\xb5\x88" + - "\xc5\x93\x10f\x12\x84\x19Ds\xc1\x1f4\xe3N\x87\xa3" + - "I#\xc5\x8b\x94)w1\xdc\xb1\xc8\x05ci\xd6\xf1" + - "\x91yz\x8a\xafd\x8c,t?B\x08&E;\xfa" + - "\xb3<>\xc1\xb3\xd1\xcb`\x8e\xcb\x8a+\x89EK\x82" + - "EW\xc0$4\xba\x11\xaf\x0a\xb2\xe8\x18\xccG\xa3\x1b" + - "\xf1QA\x16=\x02\xd0D\x1c\x8e\xf8\xb8\x00\x8bV\xc6" + - "@\xbb\xcb\xd2\xcf\x0cphe\"\xf1\xd5\x09\x88\x9f\x05" + - "\x01#}\x1a,c,1\xd5\x13\x01\x91\x90\xe0\xcf\xe7" + - "\x10~6\xe2M\xc4\x9f\xcb\x05\x7fn\x80\xe9\xaeh\xb8" + - "\x10\xf1\xb2!\xc2Ho\x86\xb1\x8c%\xceG\xbc\x05$" + - "X\xdde\xaa\x19>/\xe5\x12\x8b\x98\xe3\xa8?5B" + - "\xa3\xces1y)\xdc\xc1\x9e\xd5\xc6\xbbQ\xf3\xbc\x88" + - "\xc9\xb9\x8c\xbf\xad\x058\x8fA\xaa\xb8\xe2\xa7" + - "k\xbafk*\xabMk\xabx\xaaHV\"\xef\xd6" + - "R\xde\x1bK\x8a\xed6a\xb6M)v\xb2\xda.\x12" + - "E\x88\x96\xd4;;\x8e\xc1\xaa|\x87\xa9&\x97\xa3Z" + - "\xe1\xf40~\x96\xc7\xda\x97\x12\x0b\xbf\x04Y`\x0a<" + - "\xcdHQa\x95\xab3\xa7\xc17\xe1\x15\x0d:\x19K" + - "\xf4 nC\xc0\xfd\xba\x824\xe3\xac\xa7c\x87@p" + - "\xf6~\x92\x1c6\xe2W\x13g\x07\xc1\xd9\xaf\x82Y\x8c" + - "%V\"~\x0dqvIp\xf65\xf0\x80\xab\x92\xdf" + - "H\x9c}\xa8\xe0\xec7\x90D\xb9\x1e\xf1[\x89\xb3\xcb" + - "\x82\xb3\xdfL\x1c\xfcF\xc4\xb7@\xc0\xfd\xba\x1960" + - "\x96\xd8\x82\xf8\x0e\xc4\xcbKI\xa7Q\xb6\x93\xf1@\x9a" + - "\xfd\x83\x88\x0f)#\xef\xab\xb2\x8b$\xc7\xfd\x88?\x82" + - "\xf8\xd0\x91\xc2\xf9\xba\x97$\xc7\x83\x88?\x0e\x12D\xad" + - "\xdey)OM\xb0\x8b\xa6\x15*\xfdiw\xec\xa3\xac" + - "\xc5s)\xc3TYD\xef\xe60\x84I0\x04)J" + - "5M\x8d\x9b\x8d\xac\xb6?\x99\xe6\x96\x8b\xafN\x19\xd9" + - "l\x9a\x9b.\x91\xd6w\xeb\x96\x15x\x9fc\xb0\xcd\x05" + - "\xc7\x09\xd4_K\x02\xdc+O\x1b\xc9\xe56\xb9\x06\x98" + - "\xeb\xcf\x8a$u\xc3+w;\x03z7O\xd8)\xde" + - "\x1b\xf0!8]j\x83\x1e\xd5\xa2B\xe8\xf5\xca\x9cn" + - "%X\x14\x1fr\xe1ZK\xeb\x0etnp=\xa3\xb1" + - "\x87[\xb6\x9e\xb3\x13\xb6*\x0b\x8d<\xa8UL/\xd4" + - "*\xc0\xd5*\x90\xc6\x86\"><\xa8UT\x93\xf6P" + - "\xe5\x19\x84\xaeV1\x9a\xea\x8fB|\x02\xd1^\xa5\xa0" + - "\xbd\xf1\xa4=\x8cC|*\xd1^\x99\xa0\xbd\xc9T\xff" + - "L\xc4\xcf&\xda+\x17\xb47\x93\xf0\xb3\x10?\x9fh" + - "/&ho6i'\xbe\xf6P:D\xd0^3\xd1" + - "|\x13\xe2mD{C\x05\xed\xb5\x12\xde\xe2\x1a\xa2\xb5" + - "6\xcfd\x1b\xbd\xc9\xcc\xf0\x8ca\xf6wp\x16\x09\xa2" + - "Y\xa3\x8f\x9bM\xa6\xca\xe4\xbe\x8b\x0b\xc1\x16-\xc3\"" + - "\x9a}q\xc0=\x9b[h\xa9\xdd\x1c\xda\xb8\x99\xe4\xba" + - "\xcd\x02N\xde\x9cp\x8eFZ{Vy\x1e\xcd.U" + - "Od9O\xb1H{6\xe3\xa1\xd9\xa4\xc6[l\xcb" + - "b\xe0y\xb5\xf3V.\x9bM\xf7/2Xm\xda\xc6" + - "\x17x\xfel\xc2\x1bs\xac\xd64\xb9n\x83\xcc$\x90" + - "O\xca\xea\x1b\x0d\xdd6\x8d\xb4\xb0\xc1\xa6\xa4U\x9b\x9b" + - "jZ\x80\xf5i!sF\xc9\xa1\xd1%\xf9|\xb8\x0a" + - "\xceb,\xb6\xfbN\xdfm3\xea\xef\x88\xced,\xb6" + - "o\xbe\xef\xb6\x19\x1d\xfe\x1c\xe1:\xc6b\x07nc," + - "\xfe\x8c\x0c\xf1\x97$\x18\x0d\x9f!<\x8b\xb1\xd8a\x94" + - "\xd8/\xc8\x10\x7fU\x82\xd1\xd2\xdf\x10\xfe\x06c\xb1\xa3" + - "\x08\xbf,C\xfcm\x09F\xcb\x9f\"|.c\xb17" + - ";}\xd7\xcd\xe8\xd0'\x0870\x16{wU\xc0w" + - "\xa3\xe9)\x0d{\x0b\xae\x0e\x11\xe9hn\x82\xca\xfc\xb7" + - "\xea\xa6_{Vr\xd3\x0f\xbd\x1d\xae\xa5hP\xc2\x03" + - "\xe3\x1d\xff;\xa5\xe9\x15\xc22\x05W\x11\x91\xa9\x91\xff" + - "\x9c\xf4\xd4\x8d/\xbe>\xeeF\xb7\x9a\xaaw\xa7y\xc2" + - "V\x99ls\xa8\xf4/\x949\xc5)\xde\x99\xeb\xf6\x8b" + - "\xbd\x1bSN\xb1m\x98+rZ\xb9\x99\xfe=M" + - "\xd9H\xef\xabUn\xa0\x7fOW\xd6S\xbf\xc7(\xeb" + - "C\xbfg\x0c\xc6*7P?\xbe\xac\xac\x0f\xdd\xc4\x18" + - "\x8cs\xfe\x1d\xef\xfc\xfb\x15e=\xf5\xff\x0c\xe7\xdf\x09" + - "\xce\xbf\x13\x95\xf5\xa1\xb5\x8cA\xa7\xb2\x8e\xda\x9b\xa4\xac" + - "\xa3\xf7\x7fUYC\xcf\x9d\xa9\xac\xa1\xf7OV\xae\xa2" + - "\xfeNQ\xae\xa2\xf7\x7fM\xe9\xa7\xf7%\x95\\\xe8u" + - "\xc6`\xaa\xd2O\xf5\xa7)\xfd4\xce\xe9J?\xb53" + - "C\xc9\xd1\xf3g)+h>\xea\x94L\x08\x95\xf6\xb3" + - "\x15N\xef=GQ\xa9\xfe,E\xa5y\xfe\x86\xb2\x94" + - "\xda9WYJ\xef\x9b\xad,\xa5\xe7\xceS\x16\x87\xd0" + - ",\xa8W\xe2T\xef|\xa5\x95\xca\x1b\x94V\xaa?G" + - "i\xa5~5*\xf3\xa8\xfd&\xa5\x81\xfa\xd7\xac\xcc\xa6" + - "zs\x95\xd9!4\x1d.Pf\xd2{/T\xa6Q" + - "\xfd\x9429\xf4\x04c0O\x99L\xf5\xe7+\x13\xa9" + - "\xbdo*\x13\xa9^\x8b2\x9e~\xb7*\xe3i}/" + - "R\xc6\xd0zre\x0c\xf5{\x812\x86\x9ekSF" + - "S{qe\x04\xd5oWF\xd0\xef\x0e\xa5\x9a\xca\x17" + - "*1zn\x91\x12\xa3\xf7]\xec\xfc{\x89\x83/v" + - "\xfe]\xe2\xe0\x97*1\x9a\xb7\xcb\x94\x0az\xcfR\xa5" + - "\x82\xc6\xf5%%L\xeb\x14U\xc2\xd4\xee\xb7\x14\xa0\xf9" + - "\xf8\xb6\xf2\xb9\x8c\xf5\xba\x94\xcfe|~\xa6\xf2\xb9\x8c" + - "\xcf\x7f]\x9c=\xc2\xe5\xca\x09\xfa\xb7[9N\xe5\xaa" + - "r\\\xc6\xe7\x13\xca\xbbr'c\xf9\xa4\xaa7\x9b\xa6" + - "a\xa2\xb1C\x9e\xbd\x85\xba\x0a\xbd\xaa\x96V;\xd3\x9c" + - "\xb1|\x9fi\xe8\xdd\x17p\x95\x81\x99O\x19\x86\xb9 " + - "\xcbu\xaa\xcbU\xbb\x93\xa7m\xb8\xc8\xb0[T;\xd9" + - "#\xf3T\x9e[\xd9&\xcdR;Y$\xcdS\xe2\xd1" + - "F\xd5dQ\xd4\xbcE\xeb\x1d<\x03\xd9\x85\xba\x8ao" + - "\x88\xe2+\xf2&\xef\xe5\xa6\xc5/\xa0s\xb1|g\xce" + - "\xb6\x0d\xbdQeQ=\xc9\xd3\xce\xcff\x9d\x89\xbad" + - "\xa7\xb5\x99\x9cE-\x8b\xa7\xf2Y\x937\xebjg\x1a" + - "\x90\xa5\xe8)\xcb\x8eh\xe9\xb4\xe7\xe2\x03\x9eZ\xd0\xcb" + - "MS\x93\xdd\x97/\xe8\xe5(>\xb4\x14\xcf'\xcd\x9c" + - "f\xf1&\x8d\xd5[\xd8r*o\xa1x\xea0\x0c\x16" + - "i1\xfa\xf2F\xce^\xd0\x95\xc8\xaaLN\xf2\xbc\xd1" + - "\xcb\xcd\x1e\xae\xda\x8c\xa6\x0b\x15e\xd5\x06\xcd\xd0\xe7\xe9" + - "I#S\x9bMs\x9b\x17\xe1\xbdjZF\x15\xda\x01" + - "%\xcd\xd0\xdb\xb9\xfb\x0b\x955\x96O:\x12\x0aZ5" + - "+\x83\xf3\xc7X>\x9b\xcc\xd0x\x18p\xfc[L\xa5" + - "\x8cs\xa4\xa6Ts\xae\x9acr\xda\x16>\xca\x0b\x8d" + - "4\x83T>\xab\x9a\xcb\xe7\x98\xear|\"\xa3\xea9" + - "5\xdd\xceY\xade\xab\xa6\x9d_f\xf4[\xb6\x96\\" + - "\xcej\x9b\x90u\xe7\xd3\x86\xde\xad\xd9\xb9\x14h\xba\x9a" + - "nUu\x1e\xcd\xf5r\xd3[\x16\xc9]\x16\x9c\x8f\x84" + - "\x96\xe6\xb2n\xe7Mn\xe52\xbc\x9d\xb3\xfa\x159\xcd" + - "\xe4\xa9|\x8a\x0c\xdc&\x0d,T\x0752\x0e\xa9\xbc\xc9\xd3j\x7f" + - "\xab\x9a\x86\xae\x9c\x9eD\xab\x91v\xbd\x91\\>7\xd9" + - "\xc7\x18[M\x94\x93\xcb\xe6\x9d\x7f/bQ\xa3Q5" + - "\xbd\x9f`8\x8a\x15=\xe6b\x09\x9e\\\x90\xfc&\xa7" + - "n\x13\xd6\xcajU\xcb\xe6f\xa4+\xd9'\xe8+\xa1" + - "\xda\xac>g\xa2y)\x16\xb1Y\xef\x06\xb5\x9b\x8bU" + - "d\xb5\xbaqA\xd6r\x18\x86\x99\x934\x8b#\xcb`" + - "\x19\xb4\xd8S-jmw\xb7\xa6w\xe7\x85\xdd?W" + - "\x95\xd3iM\xef\xf6\xdd*\xacK\xd5[\xd5tW\xae" + - "^\x0c*\x9fT3\xdcT[UH;\xe3\x04\x17\x9b" + - "k\xcaj\x86\xb7\xa3\xae\x94%?\xbdu\x91a\x0b\x87" + - "7t\xe7S\xaa\xd5\x93T3\xad,B\x0c\x8b\xa7\xbb" + - "\x90\x0e\x81\xcf#s9]\xab\xad\xc2n\xe4\xacNb" + - "\x99A}\xcaa(\xad\xc8Ph;#c\x9d\x93\xb3" + - "Z5VkY\xf8\x94\xdfZ\xaaE\xc5\xf1@\xb7\xb3" + - "\xbd\xe6\xa4Y-\xaeO\xca\xd9\x8bZ\x86\xd5\xf3\x16-" + - "\xa3\xd9\xf9^\xde\xa3%\xd3<\x01D\xc4\xd6<\xdd1" + - "\xce\xd3\x8e\xd1\x1fIu\xf0L\xd60U\xb3_pq" + - "\xb7 \xd5\xc6\xcd\x8c\xaas\xdd\x16xV5\xd5\x8c\xe5" + - "\xd7\xae%8\xef\xc0m\xe0\xd6vp5i\xe7T\xdb" + - "0e\xab!\xab\x05\xf8\x02\xe3V\xb6!i\xe3(\xf2" + - "YnZ\x86\xae\xa6A\xb3\xfb\x91\xce\xbae\x9e\x8a\xa8" + - "\xbcSp\xab\x81\x8c\x9e\x06\xd7\xa4Y\xac^\x1c@\xe5" + - "s\x167\xe7\x18\xc6r\x16\xcd\xa8\xe6\xf2<_\x89\xcb" + - "\x81M7\xd0\xdb5\xd9\xd0\xf3j.\xa5\x19s9\x97" + - "S\x9djry`\xc9\x89j[\x96\xab`\xe5\x1d\xf5" + - "\xbe5\xa2\xea\x1cY\x1a\xeb\xd4\xba\xc9\xd7\xd3b\xa8)" + - "\xe4\xb6\xee\xefv\xae\xa6\xfa\x03m\xb8x\xfd\\UC" + - "\x19\x90TM\xa4\x06\xce\"j\xaa\xff$\x96E;\x0e" + - "N\x98\x15\xae\x0f\xc9\xf5\xeaEl\x9e\x8aW\xc9\xa1J" + - "\xd9q\x01M\x0a\xfa\xe5\x85;9\xb6fz\xd0//" + - "\x0e\xfbb\xeb\xa6\x07\xfd\xf2\xe2\xa0\xaf\xc0/?-t" + - ">\x88\x03\x91\x1b\xc6\xfa\x8e\xf9\xa8\xda\xce\xd3\x9e)\xac" + - "b\x7f\xbc_\xa96\xd5\xee\xf1" + - "\xeb|\x8a[\xa8\xb35\x82\xb3\xa6\xc1p\x1d\xa7\xac\x01" + - "\x92I\x9e\xe6\xa6jG4\xc3\x9fKq\x14\x9c\xb0\x99" + - "ld\x07\xb0\x8a\"\xe7\x1a\xaa\x16\x16\xb1\xc0zq\xb2" + - "\x11t\xa1\x9b\x81s^\xb7\xe3\xda*\xc6\xe2=\"\x02" + - "\xcb;\xfc]q\x13cq\xdb\xf5\xa1\x8b#\xb9\xd8U" + - "7\xf9l1\xdfi\x186\xc5\x1c\xd5^\xa4\xea\x86\xe5" + - "\x1dMe\x0c\xdd\xb0\x0d]c\xf5\xc9\xc1\x0b \xd9\xae" + - "\xf6a\x11\x04\xcbR<\xb30k\x83\x96\xe1N\x84\xa0" + - "W6\xf88\x17Z\x9d\x82\xeb7\xf1(j!\xb8B" + - "\xa7{\x03=4\xcb\xf7\x08y\x03=<\xcb\x0f\xe4\xf1" + - "\xe2\xcf\x8e\xcc\xf7\xe3x\\\xcfu\xec\xb5v\xc6\xe2\xaf" + - "\xca\x10\xff3\xb2\x04'\xf4\xeaX\xbb\x88H\x89\x7f " + - "\x01\x94\x08\xe9q|\x8e\xef\x1d\"?6J\x8f\x13\xcb" + - "\x18\x8b\x7f C{\xe0\x182\xf69\xce\xf2g\xc8%" + - "A\x82\xfa\xce\x9c\xa5\x07BGS\xbc7\xf03\xdf\xcb" + - "\xf5\x94a\x8a\xb3D\xcf7g\x1a\xa9\\R\x1c\x1bz" + - ">8$\xf0\xd6\xce,\x03/\xcet\xb5S\xcf\x8d:" + - " +\xa4KM\xda,\x9a3\xb9\xe9\xc1iM_\x8e" + - "\xaa\x05\xab7E\xfc\xa9\xdb\xe6\xe0Rv\xd0s\xb4)" + - "\x0din\xda\xb5-\xbc\x97\xa7\xe9\xa8F\x84\xadM\xa2" + - "\xf3\x8d1c\xe9|c\xc4X:4\x8cMg,\xaa" + - "\x1b:\x8f\xe0\xff\xec>\xa3\xd6\xee19\xff\x02q\xd7" + - "\x84\x9a1Is\xf2\xa3C\xf0\x04\xa5S\x9c\xa0\xb4\x8b" + - "\x13\x949t\x82\xc2-[\xcb\xa8\x0ce~^\xfcm" + - "s\x06\xa9\xd5\x8eb\xfe\x05ojt\xed@C\x171" + - "UtV\xe2\xa7\x09\x80Y\xee\x09\xc9\x049\x04e\x10" + - "\xc8\xa6\xa0\x94\xc1\x12&\xc5\xdc\xc8\x83\x13\xf3\x03\x0b/" + - "9\x07O\x9f#\x89|\xec\x062\xb9g \x80\xd2\xba" + - "\xdd;\x0c\x0f;\x87\xd5#\xe8Hc\xb8\x7f\xb8\x1d\x16" + - "\xe2q\x1a\x09\xeb\xa9\xee\xa14\x11*\x8a\xc7y\xe4\x9e" + - "\xbe\x10\xf1\x0e\xa26\x11Q\xae\xc4)N\xaa\x03\xf1," + - "HP\x09B:fH\xb6\xa7\x11^I2?\"\xa4" + - "c\x8eN^\xe8\xa4\xe6z\x90\x0a\x03\"\xd0jn\xec" + - "O\xa6\x83\xb1)\xab\x93j\xba\x8d\x9bI\x90\x98\x04\x12" + - "\xc5\xaf\xd8\xa6\xa6[\x1a$[U\xdb\xd4V\x0e\x88\xd3" + - "1\xb3\xfd4\xcf\xd8\xc8\xc9\x8a\xea\x13Y\x13U\xa6\xa2" + - "rZ\xbf9i\x83E\x92\xcb-\xef\x18\xbdOK\xf1" + - "\xb9\xa6\x91\x01q4\xd9\x9c\x8b\xa4\xf9\xc0\xc0P\x95\x9c" + - "\xcb9\xdc Q\x7fI\xc5\x91}}\x0f\xd7\xba{\xec" + - "\x93\x9d\xec\xc9's`\xcb6\x8fWA\xe0VWl" + - "\xccZ\xdf\xbd\x1a\x1bs\x9b\xef\xaa\x8d\x8d\xbf\xc9w\xcc" + - "\xc6&\xde\xe4\xbbXc\x93\x1f\xc8\xb7\x08=\xb9M\x9e" + - "\xd7$\xbc\xc5\x0e\xd0\xe1\xb8n\xf1Mn\xa5\x06p\xbc" + - "\xc16xX\x138.\xe0\x00\xe6\x0b\x17\xe7(\xf7L" + - "9\x04\xe5\x10\xc8\xeb\xa3\x8c'\x9aux\xba\x12#\xf5" + - "\xd0\x0f\xcb\x089a\x16Ea\x19\x95\x15U0\x8a\xa2" + - "2\x9e.\x88\xbe\x90&W\xc1iD\xa0\x1b\x0a\xceI" + - "\xc2\xb5U0\x86\xceI\x96\x14\x9c\x93\x94\x8c\xad\x82\xf1" + - "tN\xd2^pN\x02UU\xa8H*\xadD\xb8m" + - "\x88_\x06\x12L+= U\xc1\x0c\xc6\x94\xc5\xd4\x90" + - "\x7f&\x89\xfb\xd0\xcb$\xa9\xa8p'\x93b\x913\xab" + - "`6Q\xff\x06\x97\xfa/\x1f@\xce\xb9l\x03\xca\xd8" + - "F&g<\xed<\x9f\xd3\x06\x01]\x07\x8d\xa4\xe9j" + - "\xba-\xad\xea\xad\x86n8a\xb6\xaep\xc2:H\x1b" + - "`\x1ai\xc7\xe5\x0f\xd1\xfc\xda\xb57^\xb5qV\xf4" + - "\x0d78$\xd75H\xf3\x83\xa8v\xae\xe9\xd4\x06\xee" + - "\xdb\"\xc1h\xff.\xc3L\xf2&\x9ed2O{j" + - "\x80{\x98\x02\x82B\x13vD\xb5\xf9\x17\xea\x1a\x83S" + - "x\x80\xe9\xca\xb6J<\xd0\xcf#\xe9\xf3\xc0\x80\x8c]" + - "\x16\x10\xa7\xae\x8c=\xd2\x19\x10\xa7RH\xf0\xc5\xd7f" + - "\xf9'.\xee\x09]\xec\xcd{\x02\xe24,D\xec\xf1" + - "YB\x9c\x92\x90$]\x1cI1\x0cO\x14D\x14\xb9" + - "gs1:G\xf6\xcf\x04#a\xc1D\xab\x09\xf7H" + - "\xda\x9d\xa1&\x16\xc5\xe1y\xd30(_\xa9\xb7\xc4\xa9" + - "m\xd4\x1f\xbc\xb3\x86io\xd3\xa5\xd5\xfef\xcb\xd6\xa2" + - "(b\xbcc\xd9\xac\xa1\x05b:\\f\xe2>$\xb9" + - "\x0f\xe13\x09\xdbWR\x8b9iqL\xdd\x17\xc8c" + - "M\xef\xf64\xd5)-\xaa\xce[4\x9d\xb7ry@" + - "\xd8\xdc\xf4\xffq\xc4\xdf\xfc\x80&\xe8\xae\xd3\x0aT{" + - "\xb22\xc4\xaf\x94\xa06\xcd\xbb\xec\xc5\xde\x98M\xe4\x9f" + - "\x8b}\xe2\xe5]v\x9bi\x10\x8fw1\xaa\xd2f\x1a" + - "\x0c:\xff\x01\xfd\xf9\x86\xbc\x10\xc0^r\xb1\x18\xcc\xcf" + - "\xbb\xa6=cN\x9c\x0e\x04\xb2\xab\xc4\xaeB\x86\xe6\xca" + - "[mN0lQ\x18\xaf\xb1\xcc\x1c\x7fd\x95\"\xac" + - " \xb6b\x89?0r\x07T0\x16\xeb\xef\xf4}\x04" + - "\x05|cu\x9a\xab\xa9\x05:\x87J\xbfg\xc2z\xa2" + - "\x92\x8e>c`I>\x93\x12,\x83\xc9\x81]L\xee" + - "\x98f\xd3d\x11\xc3Dclg\xef\xc3\x7f\xea\xef\xda" + - "\xf1v\xf1\xb1\x9b<\x88\x06\xd6`Y\x9aUKV\x0c" + - ".r\xa9\xb7\xc8\x13o\x0a^\x16p\x16y\xe6m\x8c" + - "\xc5\xcf\x96!\xde$\x89\xd5A*\x81&\x9eUM;" + - "g\x02\xf7x\x08\xadR\x8b\xaa\x03w\x0ae\x93\xff\x03" + - "\x97D\xc2q\x9f\x89\xd3\xc3\x02{#$\x87*C\xa4" + - "\xb7\xc4*p\x8e\x87\xca\x10\x1f.A^Eu1a" + - "\xe4\x98\xac\xa7 \x9a\xff\xe7\x19\x17\xdd\x9c~}\xfb\x09" + - "w\x83\x0dN\xe9\xf3tM\x84\xb36\xf6tu\x99\x0d" + - "z\xca4\xb4T\xf3J\xdbT\xc9(\x0bD$=M" + - "\xb4!L-5\x9dnT3\xdc\x94\xd4\xc6\x1e\x95\x1c" + - "\xde\xa6f\xd9ZR\x84\xb3{7w\x19;\x1fbP" + - "\x1b\x0fI\x10\x04cpF\xbc\x14\x80&\x18h/\x81" + - "\xa38K_p0\xda\xe2\xf8w\xbby\x93fr\xc7" + - "\x9b\x1b\xd0Z\x85^\\-\xee\x98T\xb8\x0aq\x14\xd7" + - "\xa5\x96\x16\xe0$+\x7fA[\xe2\xa2\xd6\xe6\x06A\xfe" + - "E\x86h\xbbs\xa3\xa6-\xb0\xea\xad\xa6\x1f\xff\xea\x86" + - "D-\x9c\xe4\x87\xbf\xfa\xc1\x83\x90u#G\xc9\x81\x99" + - "\xbeXM\xb3\xdat\xf0\x82YT\xcfp\xd53\x1aN" + - "r\x99\x85\x140A\x06\x17q\xbb\xcf0\x97G\xe7\xe9" + - "]\x06vu\xb8\xd7\xd5\xcdK\xfcH9\xaf\xab\xdb\xe6" + - "\x07B\xe5\\.t7\xf6\xf5.\x19\xe2\xf7K\x00\x0e" + - "\x13\xda\x89\xfbw\x87\x0c\xf1\x07\x03\x06\xd9\xae\xe9~L" + - "\x1di\xd0h\x91\xedF\xf0~\x19\xe2\x8f\xe0Hy\xb2" + - "G7\xd2\x06\x93\xbb\xfb\xbdQ\x18Y\xb4\xaf\xe9\x84\xcd" + - "\xc5\xa2\x9d\xaa\x9er\x7f\xacN\xf6\xa8\xba\xce\xd3\xaeI" + - "T\x8b\xca\xad7\x09\xb5\x16\x9d\x96\x7f\xf1\x94xD+" + - "\xe6\xa6\xa3?\xcb\xc5\xd2\x9dN#\\,\xe2*\xe3\xc2" + - "D\x9a\xb7\x8cL\xa4f:\x1d\x8f5\x88\xebF\xe7\x8c" + - "\xa4\xb8\xcai\x93(\xae\x12m*7\x842\xa2s#" + - "\x9ft6\x03\x8b\xe2v\x10?\xe7\x19\x16c,jk" + - "IM\xce&\xa3\xb6\xb6J\x8bf\xb4\xa4\xf6\x05w\x90" + - "\x0aDH+\xaf\xb7U7\xea:\xc0Y\xd62\x16\x9f" + - " C\xfc\xac\xc0\xc2M\xbb3p\x0d)p\xb0!\xf8" + - "7D\xfd\xc4i\x9e\xf4\xf4\xea\x88\xddA\xfe\x8d\xa8\x9f" + - "\x12\xf9\x0b\x99@\x11\xb3!\xbb\xd3\xb9\xc5\x12\xd8`\xb3" + - "\xc4\x06\x13\xd1\xaa\xb1\xf9\x8c\xd5\xeb\x86\x99Q\xd3\xe4\xd8" + - "n3\x8d\x0c\x93\xb3v>ij\xb6\x96T\xd3tz" + - "\xf8\x05\xb7\xb3\x0a\x8c]W\xe7\xf7sp\x8fY\x12\xb8" + - "E>f\x83\x7fe\x1au~/gBl\xe2\x03~" + - "*\xb6\xd8\xe4\x0dy\xeaz\x0b\xefE\x15.\xef\xbe\x02" + - "\xf4\xee6#\xad%\xfb\x19\xcb/\xd2P\xfc\xb7\x19\x80" + - "\xbf\x1d\xdd\xfe\xe2\x1e\xce\xd3\xb6\x91\x83d\x8f\xa8't" + - "\xfb|c\xe0\x90\xd3Q>\xe3\xe7z\x0e\xe1\x9bI\x0d" + - "\xf2\xc2\xe0\xe0\x14\x08\xe4eU6\x93\x15P\"\x84\xa6" + - "\xb2\x8e\xec\xce@\x88\x9d\xe3\xf4\xbd\x81\x9c\xca\x81\x10;" + - "\xe7\xa6\xf4\xcd\xa4\x8do\xf2n\xc9\x949A\xd8[)" + - "d.\x10b'\x0b\x95l;y\x89\xef@\xfc^\xec" + - "\x8b\x13-u7\x99\xb5~\xe4\xddP\x10f\xed.\x8a" + - "\xc8\xf3\"\xecb\x15\x920k\x1f\xa5H@\xbak\xf3" + - "\x0c8\xde]\xb4k\x0f\x90\x86\xe8\xfb\xbe\xe5Ra\xd7" + - "\x1e&\xf3\xd8\xf7}\x87\x9ck\xd2GiX\xbe\xef;" + - "\xecx}\xdf\x84{\x82>\xee\x18\x94\x0b\xaf\xefq\x1a" + - "\xd6{\x88\x7f\x06\x12\xacN\x1b\xc9\xe5F\xce\xf6Dd" + - "\x81\x81\xa1\xa6\xfb\xd4~k\x81\x1et|\xba\x18\xb4\x88" + - "'\x83%>A@\xd4'0g?\xa8I\x9b.^" + - "\xb2(\xae;D}\xa2\x13\x15j5\xab\xfd\xc2&_" + - "\x90\xf7\xa4\x1c[Z84\xa0\xd2'?G\xbd\xe8\x1d" + - "H`P\xe9\x93\xafS\xabop\x92\x83J\x9f\xb6\xdd" + - "h&1\xa2VI\xd3s6\xb7\xdayF\xd5\xc4u" + - "\x15\xd79@C\x9c\xd1h0\x8aAvQ\xddh\xa7" + - "\xa3d\xb08y\xa0\xd8`%s\xc9\xe2\x89\xf2d\xd0" + - "\xe0\x11/ldQ#\xd8\xde\xe01\xcds\x0c\x03\xec" + - "\xa2\xeb\x19\xa6\x7f\xe2C\x8a\xa4\x97\x09(\xb6\x8e,c" + - "i\xa0\xe2\xeb\xdd\xbf\xec\x9f\xe5\xf8E\x9fr\xec\x1b\x94" + - "9\xfbQ\x8c=\xe9\x98!\xf9>5\x9d\x1e\xcc1Z" + - "@$i5\xa7'{Z\x0c\x06\xdd\xae,\xa9\xcfZ" + - "\xb6a\xf2\xff\x1f\xfaI\x85\xab\x9f\x18\x99\x8cJ\xf7\xb7" + - "\xd9\xff\x8b\xd6\x06\xd5JZ\xd5l;\xd7S\xdc\x14\x06" + - "\xe7\x179\xc8%\xc7A\xbe\xc4\xd7Ah\xe7\xba\xa2\xd0" + - "\xf5\x9a{\xa7\xa80\x88\xa1m\xd2\xcb\x1cU\xda5\x9e" + - "\x8a\xeef\x9c\xa4\xab\x81\x8bQt\xab\x08G\xeb'u" + - "\x8b\x95\xb5\x07\x92\xa6\x95-\xcb\x8b\xea\x8b8\x83\xa4\xf3" + - "w\xc2`\xd1\x9c\x99\xe4\xf1\xb3\xe4\x10\x0c\x85\xc0\xb7J" + - "\x94\xa5\xc8F+\x9d\xa3\xb3y\xe4\xd4\xf0\xbcq\x15\x90" + - "\x17\x97E\x958\xf1\x0f\xcf\xabQ!\xfd]\xdc\x17U" + - "\x16\x13\xdf\xf5\xbc\x1a\x15\xf2\xe7\xe2\xca\xa8\xa2\x12\xe7\xf2" + - "b\xad+B\x9f\xe5\x05'\xd5(6;\xe5z\xf6(" + - "UD)\xb9\xf6f\x05\x83\xb0+\xc2\x7f\xcb\x0b^\xba" + - "\x82^\xe1EaW\x94|\x9a\x17L\xb3\x9f\x98\xdd\x95" + - "Xp\x1d\x16D>\xc9\x0b\xae\xb9\x8e\xdc'\xd7a\xc1" + - "&\x90`t\xe9\xc7\xf9\x88\xe0\x9b\x1bi\x80\x9eH\x19" + - "]\xf6\x11\x96\x9cB\xb1\xd5\xd3\x83\x02at\xf9\x87y" + - "\xe7\xc4l+\x8d\xc4\x13\x09\x85\xdb`0UTu\x8e" + - "@P\x95!\x0e\xe6-\x95kU\xa9\xdd:\xb7\xb5\xa4" + - " \xef\xe2R\xc3\xd4\xb8n\xab6\x8b\x0c\xfat\xb4\xbb" + - "\xdf4\x06\xc2\xfeUy\x8f\x16\x1c\x0e\x9c5\xb9e\x91" + - "\x03\x85}A_`\xa1\x13\xb3/\xae\xb7\x0d\xac\x88\xaf" + - "\xc5: D6O\x0d\xda\\\xd64Vj\x19\xcdf" + - "\xfe\xf5\xfe\xda4y)]\xe3\xd9\xe6\x19\xd2_Y$" + - "g\xf2\x7fp\x90\x95\xe0\xba\xad\xe9<=\xc5\xfd\xa3\xa3" + - "_\xce\xf2\x80\xab~\x19iL\xe3\x85\xc64f\x15\xe9" + - "\xa1\xa3\x971\x96\xe7zjAW\x82w3\xba< " + - "~\xb6\xa3\xe5fs\x11T\xb2\xa0+\xc1\xea\xc5\xad%" + - "\x17hG\x86l\xf3\xffQ\x04\xb0\xeb\xd5$\xa7ft" + - "\x90\x8b\x99\xb3\x06\xbbB\xb7!p1\xce\xb5\x16n\x98" + - "\x15\xbc\x84\xe9\xf8\x006\xb6\x07\xee\xea\xb8\xe6\xc2\xe6'" + - "\x18\x8bo\x91!\xbeC\x82z!W\xfdCD\x9bs" + - "T\xf5\x80z\xd4\xc4\xbb}\x17F\xbd\x91\xb3\xb39\x7f" + - "\x01,\xd5\xa6\xc0\x19\x06\xa9\x01\x8fK\xce\xe3\xe4{\xc3" + - "V\xfe\xf1\x02\x15\\\xd9Lp\xbd\x9exO\xb2H\x07" + - "\x1f\xc6X|\x9cP\xb7\xf1\xff\xfc\x04\x95\xb1\xd9K\x98" + - "\x04\xbd\x03Nd\x0b\x1c\xf8\x83\xbe\xfb\"\xb5w\x9en" + - "\xd9f\x8e,Ur \x0d0/\x97\xf8\x09\x1b\xdcE" + - "X:\xcb\xc9\xd7\x90\x0a\x1c\xa2\xa9k}oR>\xe5" + - "X\xbfL\xd6=\x7fX\xd4O''\xae\x04\x15/\x80" + - "\xf8\xd9\xa4\x81k9\x17=\x12=\xb9c\xc47?\x19" + - "\x8b\x0f\x07/\xd3plbg\xe0\xdb\x09\x13\xcd@\x82" + - "\xf6\x89\x9d\x81$\xa8\x13\xd7\xfa\x1fP\xc1\x12/O}" + - "l\xe2\xb2|G\x0fG\x13b\x09\x8b\x18:w\x7f%" + - "X-\x19\x1fy\xc7\xdc\xed`\x91\xfe,w\x7f%$" + - "\xdb\xe4z\xb7\xdd\xc3\x1c`^D\xef2\xbcR\x86\xe4" + - "n\xc5\xaf\x97C0\x16\x02\xa9\xde\x94\xfd2j\x1fC" + - "\x9c\x93\xa0]22\xe1\x07eT\x81e\x09b\xa7\x0f" + - "qT`\xf9aT\x81\x11\x7f\x86r\x0b=\xee\xa8\xc0" + - "\x94\x11\xc8\xcf\x9cS\x1e\x12,\xfb e\xbcy\x06\xf1" + - "\x97\x10\xaf\xad\x10\x0c\xfb0e\x04\xf23\xea\x0cu2" + - "\xf6\x14g\xd4\x91\x87\x8b\x0c<\xc7(\xc3\xcf\xdb\x88\x7f" + - "@\x19\x84*D\x06\x9e\xe32J\x91\x0fd\x19\xdaC" + - "\xa8I\x8f\x10\x09x>\xa7\xd7z\x09ub\x95\xa7\x88" + - "\x04<\xe1\x10j\xf0\xa5!\x19\x12U\x88+ \x12\xf0" + - "\xc4Bt;\x14\xf13\x11\xaf\x92D\x06\x9e\x89\x84O" + - "@\xbc)\xe4$\x04\x1a\xc5\x98\xd2\x10\xc2\xee\x9c\x8fx" + - "K\xc8\xd9\xe4\xb5(\x82\x09\xbf\x10\xf1\x0e\xc4K\xcb\xaa" + - "\xe0t\x94\xc0!\x1cV\x07\xe2\x97#^1Y\x9cO" + - ",\x0da?/C\xbc'\xe4\xc4\x9d\x8ceL\x04E" + - "'R\x88_\x8dxMI\x15\x8ccL\xb9*\x84\x86" + - "\xcf\x95\x88\xdf\x8a\xf8\x986q\x9eqs\x08-\x90[" + - "\x11\xbf\x0b\xf1\xd3\"U\xf0\x15\xc6\x94m!\x94\xfcw" + - " \xfe\x08\xe2\xc3K\xab\xe0\x0c\xc6\x94\xbd!\x94\xa4{" + - "\x10\x7f\x01\xf1Xu\x15L`L9D\xed?\x8b\xf8" + - "\xcb\x88G\x9e\xac\x82\x89\x14T\x8f\x96\xd2K\x88\xbf\x81" + - "\xf8\xb0S\xabP\x11P^\x0b\xe12\xbe\x8a\xf8\x9f\x11" + - "/)\xab\x82\xaf\xe2r\xd1{\xdfF\xfc\x03\xc4G\xd7" + - "T\xc1\x99\xb8\\4\x9f\xef!\xfeYH\x82\xca\x89U" + - "0\x991\xe5\x13z\xed\xc7\x08\x87\xc2\x12\xc4F\x0c\xaf" + - "\x82)\x8c)\x10\xeed\xac=,Cb(\xc2#G" + - "T\xc1\xd7\x18S\xca\xc2\xd8z)\xe2U\x88\x7fid" + - "\x15L\xc5U\x0c\xe3\xa8*\x11\x1f\x85x\xf5\x97\xaa`" + - "\x1ac\xca\x880\x1dk\">\x0e\xf1Q\xa3\xc4i\xcf" + - "\x980\x8e\xeat\xc4\xcfD\x1c\xf6\x8b\xc3\x9e\x89a\xba" + - "\xe3\x8b\xf8Y\x88K\xe5t+D\x99F\xedLE\xfc" + - "\xdcp\xb1.\xd1er\x9e\xc8\xaaI\xe0\xee%\x18\x9f" + - "\xfd\xba\xf7]\xdc\xfb1M\xf5\x82G{\xc7\xe6$\xc3" + - "x\x90\xa3\xd3\xefVp5Q\xff\xeam!\x0f\x80\xa8" + - "\xcfd\x1c>%n\xf3,\xb4@\xed\x16]\x91\x83f" + - "O\x90e@\xd4gJ\xce\xc3FW\x97i\xa8\xa96" + - "0\xfa\xb8\xb9\xd0R\xbb\xa3|a_\x8f\xa7\xe1:\x8f" + - "'\xc0\xe51\x10\xf5Y\x99\xcb'U\x93\x82p\xc1\xec" + - "oT\xb3jR\xab\xb5\xfb\x83m$\xb3\xb9\x0e\x9e\xc9" + - "6\x0er\x16\xdb}\xf2\xa2\xc1\xef(9\xfd\x99\xc7\x90" + - "\xc7\xa1B\xe3rR\xd7:T-\xbb\xc1\xee\xe1\xa0\xab" + - "m\x9a\xde\xdd\xa1\xc9\x05\xd9\xab\x8ao-y\xc6\xdc\x80" + - "\x12\xa77\x92\xdb\x1b#\xc53\x1d<\xc3\xe4l\xe3\x80" + - "\x84\x18I\x93s}\x8e)\xa1\xe2\xa4s\xcb\x1a\xd0\xbc" + - "\xedr\xf5\xa8\xa1\x07\xee\xad\xba\x92\xc3\xb9\xb5\x9a\xcdh" + - "I\x9c\x0d\x06\x03^1\xe8\xd5,g.ZY=\xb7" + - "\xb9\x19$&#\xd3\x86\x0f\xb0\xda&S\x1d\xf8\x80#" + - "\x12\xa0\xd2\x17=\x9ev\xb9\xd2[\x0e?RH\xb8\x14" + - "\x99L\xf4\xe3}\xcc\xcbY|M\xb7\xd5\xe5\xbcx\x99" + - "\xf8\xca\x1e5g\xd9\x1d,Zp\xef\xac[\xb7,w" + - "\x84^\xfbVv\xc0;;\x0d\xdb62\x09\x83\xd5\xd3" + - "\x84\xf8\x95\x93\xceU>h3\xb9ES\xec\x8e9\xe7" + - "\xc4\xe7\x08\xb5\xd9\xfb\xb8]\xd1\x19G\xa1\xb1\xde\x90K" + - "\xd5k\xc6 .\xc8I\x8e\xfa3\xd5\xd7C&/\xf1" + - "\x0f<\xa2)\xd5V\xdd\xa4\x0dyK\xcdd\xd3\xbc]" + - "\\\x8c\xfa\xe2\x1b\xcf\xadj\xb6~J\xb3n\x9b\xfdE" + - "/\x1c\xeb\xbf\xd0S?'O\xf7\x1d\xa1\x91\xe5\xbc\x1f" + - "\x86A\x81\x1d\x0d\xc3\xbc<\x0b\xc3\xc2\x03\x8bN\xd2\x85" + - "\x8b\xd4\xde\xdav\xd4\x9b\xc5\xa1\x97\xfb\x09\x90\x18,\xc9" + - "7\x1a\x86\x99\xd2t\x1aH\xf0\xa0\xa3\xd39S\x99 " + - "\xa1\xa9\xef\xd4\x89\xd8\xc1\x0b\xd8^;_x\x01{P" + - "\x9d\x9c.'\xf8:y\xe0\x1cq\xd6`\xe7\x88\x1b\x06" + - "\x0b\x1e\x9b\xe5'\x09\xf1t\xf2\\\xbb\x1fQ\xf6\xffX" + - "\xfd\x1e|t_p5\x9a1\xf2\x01x\x89Ice" + - "\xab\xfcT\xda\xb1\xb2\xce|;Or\xad\x97\x9b\xee-" + - "^/S\x15\x8bp\xdd\x0e\x1ek\xe0P7\xc9\x10\xbf" + - "\x03'%$&e\xeb\x9c\xc0Y\x87\x14\x16\x93\xb2\xad" + - "\xd3?\xebp\x8f5\xee^\x15<\xd6\x18\xea\x1ck\xcc" + - "\x09\x1ek\x80s\xac\xb1\x8c\xb1\xf8\x832\xc4\x9f\x95\xa0" + - "\xdeL\xf6v\x18}\xde\x0d\xe1\xe2,{i\xaef\x13" + - "\xd5\x15\xe4\x16\x10\xf5" + - "\xd9\x8f\xeb\xd7C\x8d,\xa1\xf6\x82\xb8\xb3H\x0e97" + - "'k.kk\x19o\x92\xea\xa9\xa9\x80/\xc3c^" + - "\x0e\xff\x13]i_\x09\xe2B[\xca\x1fXO!3" + - "\x82\xa8\xcf\xde\x9cn\xf4p\xd5\xb4;\xb9\xcaj\xed\x16" + - "\xc3\xb2\x03\xe7B67u\xd5\x06\xad\x977\xaf\xccr" + - "\xb3V\xe3z\x92{\xf7\xec\xc5;;V\x82\xb8K\x16" + - "x\xa7\xa6\xdb\xdc4sYj\xd1\xbf\x81\xe2<\xd1\xa6" + - "\xb2\x88\xa9f\x82\x99\x00\x84n\xca\xfc\x9c\x01I\xd59" + - "N\x84\xa9P\x19\xfc\xde\x9b\xd0\xdd\xbc\xd2i_X:" + - "}\x90Ro\xa6(\xbf\x8dw\x7f*\x10\xcc\xaf\x89\xfb" + - "Q\xb5\x85Q\xc9Vgn\xda\"#m\xb3\x08\x12\xaf" + - "7\xa2\xce\xdc\xf4AP#\xa7\xa7\x16\xe4l\xc8\xe6l" + - "\x8aM\x0eDQ\xbbt,9t\xdc\xde\x9chn_" + - "\xd4\xdc4-pVw\xb2:\xd3\xd9?\xca\xc0\x16\xbc" + - "8\xd0h\xe8]Z\x0a\x97\xac1\xadZVA$\x88" + - "\xc86Z=\xcb\x8b\x04\x89\x98\xd9\x10\x88P\xf7\x12i\x84\xd1P" + - "\xa7@\xe5\xa1\xc1\xec\\e(\x0f\x02y:\xdc\xec\\" + - "\x15\x84\x07b\xf5J\xdcX\xbda\x85\xb1z\x117V" + - "oVA\xf8i)\x08\x818\x82N\x1a\xbc\xf0\xd3A" + - "\xdc\x859\x1c9\xb8\xd1\x8d\xc5\x17)\x06\x0b|t\x92" + - "\xc7\xbay\x7f\xb2\xde_\x9a\xf7W\xd7\xffE\xed\x94\x8a" + - "\xfc\x91VD3y \xb9\xac\x08\xfc\xa1\xf8\x0e)\xd6" + - " \xb2h\xcd^E\xd1\x1e\xe7\xac\xa5h\x8f\x99\xf3E" + - "\xb4G\xbb\x13\x14\x94\xb7s\xa6\xde\xc2\xbb\xe8\x8a3\xfe" + - "\xdd\xaeu\xf70\x08\\P\xad\xa7{\xac> \xd1\x1d" + - "\xd6\x1e\x9b-\xe7<+\x9e\xcc\xe3\x9f\xee\x83\xff8t" + - "\xc7\xf1m\x06\xf2\x159\x87\x04#E<\xff*\xea\xfe" + - "\xe8%\xd4\xfd\x11\xf3\x19\x93\x8d\xe5\xf9>\xd5\xcc45" + - "\xb7\xb5\xb3zq\x85\xcf\xbf\x9bM\x8e\xe7AB-\x0a" + - "'\xab\xcd4\xa2\xc9\x16\xa3;>\x14\x02\xdf\x98\x8d\xc5" + - "\xe6\xf8\x9f\xe4\x88U\xcc\xf7S\xf0\xc7*\xc6\xae\x16\xf9" + - "\x1c\xad|c\xdb\xc2\x0e-\xc3-\xc6X\xa4\x95g\x82" + - "~\xeb\xf9\x81D\xc3\x9e\xe3zl\xd0q\xed\xd0\xbc\x17" + - "\x1b\xb9R\x12~\x11\xa7A_\xd7\xf5\xfa!x}$" + - "\xc33P\xe9wH\xf0\xb5\xda\xaci$\x03\x0a\xb27" + - "\x92/T\x90\x03\x09\x8ak)Cq|8\x04>\xd0" + - "\x11\x9b\xb8\xd6\xff\xeeLl\xe2=\xfegCc\x93\x9f" + - "\xcb\xf7\x956\xef\x98\xb2%\xb2\x96\xc5f\xae\x0d|\xee" + - "r\xa6\x19\xf8\x88\xc5\xcc\xb5^6]\xd9r\xe2e\x1a" + - "\x0d\xd3\xe4I\x9b\xa7\x82\xd9\xa1\xbcj\x92%RH{" + - "\x972\xa1)\xef\xa6M\x96\xe8lv^\x8a\xb9\x95k" + - "\xad\x8e\xfe,\xf7\x9e\x05\xe7YV\x90\xceg~\x01;" + - "p,\xa4\x01\xa1\xbb~:\x1f3\x98\xce\x07\xbcl>" + - "\x0f\x14\xa4w\x0d;\xb7(\x02\xe9]/t3F\x85" + - ")\xba\xfc\xb6\xc2k\x11NxJ\xd19l\xac\xd4q" + - "\xb6/&\xdc;\x86\xa5p\x96\xd2A2^\x85\xc2\xe2" + - "LU\xa3\xf8\x94\xb4{tJ\x86R\x87\x93d\xc9q" + - "nyV\x99+\xb0\x9d\x0c\xe7\x0bXm\x17\xe1^\xde" + - "'gA U@\x0b>1y4\xe0\x10\xd3rJ" + - ",\xd6f\x80EZQs\xa3\xdc<\x17*\xfd\xef\xc4" + - ":\xa2VT[\xc4!m$5\xbb\xffd\xd5\xb2\x86" + - "\xe5(|\xcd\x8d\x83V\xe8\xe5\xa2\x81\x93V@U\xa9" + - "\xc3\x98\xab\xb1z\xd3\xb2\xe7j+}\xa7\x93O\x18D" + - "{\x1c\x02\xa3\xf2\xc8\xfc\x8bmH\xd3@\xf60\x85\xf8" + - "\x04\xb7\x88-\xb5y\xd45F\x1a\xeb^\x1a\x9d \xf9" + - "y\xca\xc6K\x93\x90Z\x10>S\xf2\xc3\xd0\x95\x89\xd2" + - "tT\xdb\x11\x9f*\x05\xf2\x94M\xa6\xfa\x13\x10?K" + - "\xf2\x0f\x0c\x95itW\xf5L\xefN\xaa\x13b\xa8\xcc" + - "\x94\xda\xdd;\xa9\xe7K\xce%\x1d\xa4\xae\xd9t7\xf4" + - "\\\xc4/\x94\x9c\xcb8\xf4\x91~\x09\xa9\xe5B\xc4;" + - "$\x87\xea\x90\xba\xe2tW\xb5\x0d\xf1\xcb\xa4@\x9e\xb2" + - "\xc5\xd4\x1f\xff\x0eky\xb90\x06\x97\xd2\x9d\xd7\xcb\x10" + - "\xef\xa1\xab\xb6%\xe2\xe8\x87S\x7fR\x88g\xe9\xae\xad" + - "s\xab'#\xcd*\xb8\xdbZQ*\x8c\xc7\x15\x84\xa7" + - "\x11_Iwm\x87\x08\xe31G\xed\xf8w^\xa3\xe0" + - "\xdey\xc5yX\xe9\xdem\xa5\xbb\xb6h\xac\\X\x8f\x9b\xa9\xff\xb7\"~\x17\xe2\xca\x10" + - "a=n\x93\xd0\xda\xb9\x03\xf1{%\xa9 QnA" + - "\x06]'\xf4\xd2\xcdo\x9a\x0d&\xd4%\x87\xb1\x9f%" + - "\x0dyy\xa2\xdfBy\x9d\x09b\x8d=Z:\x05&" + - "\xd7\xb12\x1b\xb4\x84\x1e\x0b<\x9555\xc3D\xfaG" + - "I\xed\xe4Y\xd5\xb5\xa4\x9fLU\xcfe:zL\xae" + - "29\xe5_O\xa2\xf3\x83\x0e-\x83\x16\x8d\xb3\xd3\xeb" + - "3<\xb3(\xe3\xc5\x03\xe1\xcfv\xcb\x0f\x0fr\xd2\x1f" + - "\x18\x0cL\x7fT\x99T\x1a\xcd0g\xd7\x0c\x15\xde\xe7" + - "\x08_\xe9\xcd\x09\xb6\xd2\x16hE\xfcl\xd0\x99l\xe8" + - "E`\xa2\x87\x91\xf4*\xbeW\xf9?\xb9\xe9W\x9c\xa2" + - "\xde\x91\xa9\x13\x9ff,>U\x86\xf8\xb9N\x9c\x0f\xca" + - "\xd4s\x9e\xa00D\x88_\xe8\xc6|7\x1a9I\xb7" + - "\x9d\xd07\xffp\xa6 >\xacC\xcbH\xbc\xa8\xca\x80" + - "\xd8\xae\xd0\xc9\xbe0\x93\xe8m3\xd2\xfd\xed<\x9a5" + - "L\x0a\xf7JyLb'\xed\xa6\x1dH]\x0fJ\x81" + - "<\xb5\xbb\xe8\xc6\xf9\xfd\x88?B\\b\xb8\xe0\x12{" + - "\x89\x1a\xf7 \xfe$q\x89\x11\x82K\xec\xa3]\xf0\x08" + - "\xe2O\x11\x97\x18)\xb8\xc4~\xda\xc5O\"\xfe,q" + - "\x89/\x09.qPB\x99\xf2\x0c\xe2/\x11\x97\x18%" + - "\xb8\xc4a\xc2_@\xfcU\xe2\x12\xa3\x05\x978J\xef" + - "}\x19\xf1\xb7%'\xd4\x12\xb9\xc4\x9b\xd4\xffW\x11\xff" + - "3q\x09'F\xf2\x984\x92\xb1\xc4\x1b\x88\xbf'\x89" + - "\xfb\xf8\xc8$\xde\xa5\xeao#\x1c\x92\x9d\xfb\xf8C\xe8" + - "\x93:\x93\xdcO\xea\x0c\x97\x9d\x0b\xf9\xc8$\xaa\xe5\xe9" + - "\xee\xb7p\xce$\xd7\x8dsn<\x91\xbe\xd0\xe2\x7f\xc3" + - "\xe6\x94\xb0`\x123\xc9#u\x16\xe2\xe7\xd39p\x89" + - "`\x12\xb3\xc9iv6\xe2M\xf4%\x99\x88`\x12\x0d" + - "\xe4\xa39\x1f\xf1\x16\xfa\x92\x8c\xe3a\x9aG\x1e\xa9\x0b" + - "\x11\xef\xa0/\xc9\x94\x09&\x11\xa7/\xc6\xf8\x9f\xc2Q" + - "\xca\x05\x93XL\xef\xbd\x04\xf1\x14y\xdf\x86\x88/\xc9" + - "\xa8\xe4\x95\xbb\x1c\xf14\xb9\xa4\x86\x0a\xd7\x93F\xe7\xd2" + - "\xbes\xefTY\xb8\x9er\xd4\x1f\xdb\xf3\xb4\xd5\xc8\xc2" + - "\xf5t\x03\xf5\xff:\xc47\xd1\x97d\"\xc2\xf5\xb4\x91" + - "\\^\x9e\x07N${\xf4\x8cg'\xe9\"\xab\xef\x17" + - "Y\x17]\x82\xedQ\xad6\x14\xac\"\x08\xc91\x18V" + - "\xf7\xa8\xd6_i\x1b\xd4y:\x19W\xf4\x8d\x1196z:\xd9\x86" + - "\xd5c\x19\xab\x17ilj\xd3\\MM\xa5\xffN\xa3" + - "\xffN\x8f\xf0\xe9\xfc\x1f\x9e{\xb8\x9f\xc9p\xbc\x11\xdd" + - "\x89Z\xa3\xe8\xf5\xed\xf4\xfai\xe2\"\xc2DqW{" + - "\x8cH\xf0\x91\x86bj7" + - "Yb\xfe\x8d\x802'\"\xf5Qj\xff\x11\xc4\x9f\x02" + - "\xc9U\x11\xa3\xfe\xaa\x097\xebj.|\xbc\x9e\x87\xb7" + - "\xd8\x9fD*\x08_\xc9d{\x9aG.\x01pz!" + - "\x18p+{\x14\xe1\x06\xec\xfb+\x0bQ\x9fD\x82\xa5" + - "\x8e\xa3\xdbm\xb1\xc0\x83.R1\x894s\x81\xafC" + - "d\xb9\xa9e8\xe8\xb6\x9a\xa6D\\\xbe\xbcp\xb3>" + - "\xb1\x88f\xf7C\xd4\xffh{\xf0\x8d\x17\xe6R\xac~" + - "\x91f\xe5\xd44D\xf3/\xd4\xe8\xea5\xdf\x7f\xf1\xc6" + - "\xc2.\xbb\xf7\xf2\\\xda/\x0a\xba+\xfa\xecAO\xae" + - ">\xd3\xa9\xabZ\x9a\x8e\xad\x9f\xc8>>\xe6\x81\x1f_" + - "\xf1\x1b\xba\xabI)\xec)\xa9\xde?\xfe\xee\xc42\xff" + - "\xae\xa6\xab>f\xda\x83\x87\xc7N,~n\xbe\x7fx" + - "< \xea{\xf0d\xf8y\xbb'G]d\x90\xf6b" + - "\x03\xb8\xdf7\x88\xfa\xdd\xfe\xc2\xcbGEl,\xe1d" + - "\x95\xd1\xec\x84&w\xd3g\xafJ\xa9\xe31r\x10\xc7" + - "\xcaf1V\x9b\xc9\xd9\xc9T}\xaf\xc6u]\xfd\xdf" + - "(\xda\x81\xacy\xd8\xf0\x85r\x08'+\xff\x1f\x7f\xbd" + - " \xf4\x81\xbes\x03S\x8e\x81\xf3\xa5\x0b\x91\xdaiY" + - "\xc1\xf5\x16\xc9K\xed\xb4\xac\xe0zK\x08\xdc\xd4Nk" + - "\x0bR;E\x07O\xedD\xdfC,\xa1k/k\x83" + - "\xd7^\xe8S\x0b\xc8\x00>\xa1K\xfa\x9fy9\x9f\"" + - "\x8eA\x1b\xa6dJ!\xd41+I\x85u\xdc%\x15" + - "d\x00Wz\xc9\xa0\xca\x9c,\x15#\xc8 \x1c\x8e\xf8" + - "82t\xc5g\x0f\x951dH\xfb\x06\xfc\x10\xe7:" + - "\xcfDiC\x81A>\xd4\xd1Ug\x92\x0a\xee\x1b\xe4" + - "\x15eBW\x9dM\xed\xfb\x06\xf9)%B'm&" + - "\x15\xbc\xc9K*%\x97\x0b\x9d\xb4\x95L\x02/\xa9\x14" + - "Z9\xc3(\xa7\xd4,\xd7N\xa7\xdcQ\x95\x8e\xdd\xaa" + - "Qu\xcf\xbe.\x8aFS\x93\xbc\x89\xdb\x9cE\x93v" + - "A\x16\x7fJd\xa8\x16\xc1j\x9fjr\x9d[\xae\xab" + - "\xc4\xf7Y\x17\xde\xef\xc9\x1a\x16o\xd3\xec$\xf4\x0cH" + - "\xf8\xef\x95\x0c\x96\xf0\x1fK\x17\xab}\x0bX-=V" + - "\xf0\xd4b\xb5o\x11\x88gr:\xf8\xcfX6\xcf\xba" + - "\xc9\x10\xbd\x07\xfc\x8eR\xda\xb9\x80\xe3\xdd/iS-" + - "\x0b\x8b\xfc2\xcdj1\xfa\x12vA.\xa8\x1e-a" + - "\xe3+\x99\x1c<~t\x9b\xa5\x14\xa5\xfe!\xa3&\xd2" + - "V\xb2z\x9e\xea@)\xef\x9e\xcc\x15\x7fIa\xf8[" + - "\xe3\xde\xbb\xe0\xf2O\xbd\xb8\x97\x9c\xa3\xab\xb2z\xbd\xe8" + - "3\x8b\x83j,\x8d\xaa>\xe0\xd39!\xf1E\xb6\x82" + - "\x8f\x1eTI\xb0\xba3G\xfe\xbc\x01\x89sB_p" + - "b\x134\xa3\x9f\xf1\xc4\xfe\xba0\x9afW\x87eH" + - "\\\x1fv\xb61\xe2\xeb\x09\xbf\x06\xf1\x1b\x11\xafu\x9c" + - "\xa47\x10~\x1d\xe2\x9b\x10\x9f\xeexI7\x86Qv" + - "\xde\x88\xf8\x96p\xe0\xeces\x18\xd5\x87M\x88\xdf\x11" + - "\x0e\x9c\xbdl\xa5vnE\xfc\xaep\xe0\xcbU\xdb\xa8" + - "\xfe\x16\xc4w ^V&\xb6\xf1v\xc2\xef@\xfc^" + - "\xc4\x878&\xe7\xdda\xdcf;\x10\x7f\x10\xf1\xa1C" + - "\x9c\xfc\xf9\x84\xdf\x8f\xf8#\x14T:\xd4\xc9\x9fO\xf8" + - "\x1e\xc4\x9fD\xfc\xd4\x0a\xb1\x8d\xf7Q\xff\x1fG\xfc\x19" + - "\xc4\xa3NP\xc3\x01z\xef\x93\x88?\x8b\xf8T'\xa8" + - "\xe1 E\x83>\x83\xf8Ka\xe7\xd6\x1fn\xef\xc3\xd4" + - "\xce\x0b\x88\xbf\x1avn\xfd\xe1\xf6>\x1a\xa6\xd0f\xc4" + - "\xff\x8cx\xd8\xf1K\x1d\xa3\xfe\xbc\x8d\xf8\x07a\x09\xa6" + - "M|\\\x12\x1b\xfc8\xbd\xf8\xcfX\xf01\x16\x8c\xdc" + - "'\x09\xa3\xf3D\x18\x19\xdd\x07a\x19\xdaK$\x80Q" + - "\xc2\xe4\xfc\x9c\xa2b?\xc3\xea\xc3K$\x88M\xae\x11" + - "&gu\x09\xe5\xa3(A\xf6W\"\xc1\xb4\x8a'$" + - "as\x8e(\xc1\x8e\x0e\xc7\x82q\xf8\xc0\x18\x106\xe7" + - "\x98\x12\xec\xd0\xe9\x88\x9f\x89\xf8XI\xc4;L$|" + - "\x02\xe2g!^=\\\x04OO+A~9\x15\xf1" + - "s\x11\x8f\x8d\x10q\x10\xe7\x94 \x83:\x1b\xf1&\xc4" + - "\xbf4J\xc4;4\x94<\x81\xfc\x0f\xf16\xc4'\xcc" + - "\x12q\x0d\xad%(\x07.D\xbc\x03q8\xcd\x09\x9e" + - "\xa6\x01\xb4 ~\x09\xe2\xe5\xa7\x8b \xe9\x85\x84\xb7!" + - "~\x19\xe2\xd3\xc6\x88\xb0\x86\xc5\x84w ~9\x0ex" + - "\xd2/$\x11\xd7\xb0\xb4\x049\xe9%X\x90\xc2\x07\xbe" + - "\xfc\x0d\x11\xbe\xa0\xd2D\\\x8ex\x1a\xf1qsE\xf4" + - "\x82V\x82\x9af\x0f\xe2664\xecII\x84I\xaf" + - "(AI`c\xc1\xd5Xp\xc6~I\xc4I_E" + - "St%\x16\\\x87-\x9d>N\xc4I\xaf+A\x11" + - "t\x1d\xe2\x9b\xf0\x81S~)\x89@\xe9\x8d%H\x14" + - "\x9b\xb0\xe0\x0e|`\xbc,\x02\xa5\xb7\xd2\xab\xb7 \xbe" + - "\x03\xf1\xca\x90\x88\x94\xdeN/\xb8\x0b\xf1\xfb\x11\xaf\x19" + - "/\"\xa5w\x12~/\xe2{\xf0\x05\xca\xaf$\x11+" + - "\xbd\xbb\x04\xa9\xe2A,x\x1c\x1f\xf8\x9a\"b\xa5\x1f" + - "-A\x1az\x04\xf1\xa7\xf0\x81\xe1OI\"Xz\x7f" + - "\x099\x94\xb0\xe0Y,\xa8zZ\xaa\x82\xaf#\xbd\xd3" + - "\x13\xcf`\xc1K\xd8\xd2W:\xaa\xe0l\xa4w\x9a\xbd" + - "\x17\x10\x7f\x15\xf1\xd3\xbeZ\x05\xe7 \xbd\x13Y\xbc\x8c" + - "\xf8\xdb\x88\x8f\x9e\\\x05\xe7\xa1\x1aPB\xb7\\\x11\xff" + - "\x00\xf1)S\xaa\xa0\x1e\xc9\x9d\xc8\xe5=\xc4?\xc3\x17" + - "\x7f\xf5\xd7R\x15\x9c\x8f\xf2\x9ef\xfb3,(\x8dH" + - "\x10;sa\x15Z$J8Bq6\x11\x94\xf7\x11" + - "\x09\xa2\xbd\xcd\xdd\x86g\x8d\xa9\xc1\x1f\xbdm\x9a\x1f\x88" + - "\xd0\xdb\xa1\x9a\xdd\xdcna\x91@\x82\xcc\xd5\xfd\x94e" + - "\xd4K\x9f\x19\xedo\xe2\xdegPW\xe7\xb2\x09\x9b\xfb" + - "\xee\xdd\xd59\xad\xe0w^\x15M\xb62Y\xd3\x07\x01" + - "U\xffPb\x197\x97\xcfEQ\"\x1b\x81\xc7Er" + - "%\xce\"\xdc\xf4_\xda\x93KQ\x0aO/\x15K." + - "\xd3\xa2v\xb7Z\xac\xe0\x13\x19\"O\x0f+H\xd4c" + - ":\xb9L\xc0\xe6\xe2*c0\xeay\xb0\xa4 \xc5\xf6" + - "Iq~l\xff\xcc\xd9}\x1f}l\xd4\x15|e\x8e" + - "\xd7\xa2\xb7\x91\xdc\x05~\xf6\x15\xae\x9a\x8b4\xde\xc7\"" + - "\x8dj\xe6\xffb\xec\x9cL-\x113\xd6j\xa4X=" + - "O\xcf\xd1\x02\x1f\xac\xfd\x87W\xa1Nj\xa2!\xf5\xb4" + - "\xab}\xfe\x1aw\x15\xae\xb9\xb3\x9c\xde\x09\xfd`&\xdc" + - "\xff\xd90\xeb\xceZmiU\xd7\x81\x9b\x8e\x06\xe2k" + - "*\x83\xdad\xd4\xdc\x9c\xb4\x06\xfarM\xefn\xa7k" + - "\xd4^\x0c\x82\xa3\xda\x83\xab\xdb\xcb\x0b\xf4\xa2\xd9/4" + - "\x01\x0b,0\x17\xecu\x02;\x98\x1c\xb8\xe8\x97\xe2I" + - "\x9e\x9ek\x98,\xda\x913\xf5\xc2\xeb\x0a\xad\x86\xcej" + - "\x8d\x82\xefC\x0f\x96\x84\xd3k\xa2\x96\xe2U\x8a&\xd0" + - "\xc8\xb1\x88\x9e\x9a>\xd0\x0et\xf2\xd2\x03\xe9Q\xdcd" + - "\x81\xaf\xe7\x15E\\D\xdb\x03\x89\x91\xf2\x0eM6\xb2" + - "\xfat\xce\xb2\x03{\xf6\xff\x8fU;\xb8\xb25H." + - "`\x11\x0e3\xd5\xd3\xb5\x1a\xe8\xfa\xac\x7fb\xec\x9aR" + - "\xcd\x84{_}\xf3\x0e\xa4\xe7\x11\xee\xe5)\x83!\x00" + - "\xf9;;\xb7\xdc\xb2-\xfa\xf3\x1f2\xa5\xb5 \x95\xda" + - "9dF\xf99\xd0B\x8e>5\x9b\xdc4\xfe\x17\xe8" + - "\xc2\x8e>\xd5@\xb8\xd7\x97i%\x0d\x8e\xaf\xbe\x99\xfc" + - "=~g\"C\x84\xe24\x8fN\xd3\xfdc\xed\xd2\xa1" + - "Bq\x8a\x93C\xc6O\x9aV6\x07\x84\xe6\xb4\x98z" + - "\xe4%B\xa3\xc0\xc9(\x80\xb2\x94\x0c\xc4\xcb\x10\xef\x01" + - "\x09\xa2\xa9@\xde\xe2h\x7f\xf0Go\xe0G\x81\x81S" + - "\xdb\x1bLo\\O\xbf\xbe\xe9\xef\xcd\x82\x9f\xab\xb3\xe2" + - "v\x80OjX\xdc\xa1\xe6\x82\x9c\x94r\x8b\x17f\x8a" + - "\xaa%>\xea'7\xa0<\xd6d;-\x9fGl\xf9" + - "x(\x9f\xcf\xe7\xff7\x99i(\x08\xd8*\x8a\xf6\x9f" + - "5X\xb4\xff,?\xda\xbf\xbe\xafO\xd5;V\xba\xc7" + - "\x7f\xf4\xb3\xdd\xfb\xf9?\x08\x06k\xe5\"\xb3\x8acX" + - "\xd0\x1d\xe1\xf8Pq\x8e&1\x16k\xbe\xad\xe8\xbe\xbc" + - "\xccX,\xbe!\x98P\xd6\xb9\xc4\xba\xf4\xa6\xc0M\xcb" + - "\x01_\x90\x95\x03\xdfy\x1e\xf0\xe5\xd8\xc0\\\x0f\xf8d" + - "\xec \xd9\xb9N\xe6Tv\xbf\xb7\xec} \x18'\xf3" + - "jo\x83\xad\xa0s&\xff\xdc\x05\xbc\xa0\xeaI\xc1\xa0" + - "jo\x83\xf5\xd3\xb9\x8e\x1f\x11\xed\xc6\x9d\xad\xa1\xfaW" + - "\"~\x9d\x1c\x08<[G\xe71^\xb4u,,>" + - "\xcf\xa7\xac'\xdc\x8f\xa0v?\x1ev\x83<\xac\xe0\\" + - "'\xe2\xf806R\xfb~d\xb5{(\x7f3\xb5s" + - "#\xe2[(d\xd9\xf1al\xa6v\xfc\x88\xebr\xc7" + - "\x87\xb1\x95\xda\xb9\x15\xf1\xbbd\xe7>>\xee\xe1m\xd4" + - "\x8e\x1f\x89=\xd4\xf1al\xa7v\xee@\xfc^\xd9\xf1" + - "U\xe0\x1e\xbe\x9b\xda\xf1#\xb4O)\x17[x'\xb5" + - "\xb3\x03\xf1\x07\xe9\xbc\xcdII\xb2\x8b\xf0{\x11\xdfC" + - "\xe7m\xa7\x0a\xe3g7\x9d\xe7\xf9\x11\xdd\xb1!nD" + - "\xf7\xd8\x82\xfb\xa4\xc3.sC\xba\x91\xa7<\x82\xf8S" + - "n\xf4\xfa\xfa\xb3\xae\xff\xbe\xfd\xd0\xd8\xb7\xdc;\xa9\xca" + - "Ta\xf6\xec\x92G\x16\xbc\xb3J|\xdcP\xd9M}" + - "\xf7\xdfY}\x8a0|\xf6\xd2\xdaR\xb8\xf8\x93\xb2s" + - "y\x13\xed\x9e}\xd4w\xef\x9d\xb1\x9a\xa5\xc2\xee\xd9O" + - "\xed\xfbw[\x87w\x0a\xbb\xe7\x00\xe1\xfe\xdd\xd6\x11I" + - "a\xf7\x1c$\xfc)/\x1c}dJ\xd8=\x87\x08\xf7" + - "\xef\xbc~\x89\x0b\xbb\xe70\xe1~\x98\xfa\xa8\x19\"\xce" + - "\xfb\x08\xe1\xfe]\xd8\xd1s\x84=t\x94\xce\x04\xfd\xf0" + - "\xf5\xd3\xc6\x0a{\xe85\x1a\x97\x17\xbe^p&\x18\xed" + - "\xe7\xaa\xe99\x05Rj\xff<}1}\xad\xc5\xab\xd0" + - "c\xe4\xbc\x1f\xf5\x19\xca\x9a\xe2\xfd\xb4\xe8\x8b\xc9^8" + - "\xe2J\xff\xe8n\x11O{\x81\x04+)\x9b\xa4\xfb\x13" + - "\xfa\xbdZ\xfd\xc1Z\xfd\x85\xb5Vy\xb5V\x05k\xad" + - "*\xa8Uo\xf5v\x04\xbe![k\xf5.lo\xf0" + - "\x12\xd5\xab\xdd\xdc\xff.X\xef\x85\\M\xdb=\xc1\xb8" + - "\xe1\xa0|\x90\xedNo\xc4\xb6\x9a\xbb\xc8;:K\xf1" + - "\xb4\xad\"\xef\x07\x0f\xab\xefV3\x19\xd5\xfb)g\xa7" + - "\xb9M\xca\xd9\xe9\xfe\x9f3\xfc?\xcf\xf2\xfe\xd4\x03\x7f" + - "z\xf1\xc2\xab\xbbL\xbe\xe2\xa2\\\xc6\x0b\xbe\xb2\x97\x8b" + - "oQ3\xb0\xfe\x81\x0b\xc8M\xca\x9aV\xf5\x82\xef\x08" + - "tx\x1cn6\x85\xc9x^E(s4\x08\x8a." + - ":\xdf\x8b\xe6)w\x9c\xb1\x8b\x09\xef\xf0\xa2sJ\x1d" + - "gl\x86p?:g\x88\xe3\x8c]Ax\xda\xcb0" + - "\x0f\xce)\xcd:\xc2\xafF\xfczr~:\xa74\xeb" + - "\x09\xbf\x06\xf1;\xdc\x8c\xf7\xe4\xdd!\xdc\x8f\xb6\x19\xe6" + - "0\xb8m\xe4D\xbd\x0b\xf1\xfb)jg\x9b`d;" + - ")\xfe\xe0^\xc4\xf7 ^\xe5D\x17\xed&/\xe7\x83" + - "\x88?N\xce\xd5;\x05#{\x94\x9c\xab~<\x84\xe2" + - "\x9c\xc8\xec'\xe7\xad\x1f\x0fQ\xf9/\x82\x91\x1d\xa4\xf6" + - "\xfdx\x88S\xee\x12\x8c\xec0M\xa7\x1f\x0f\x11\xdd." + - "\x18\xd9Qr\xd2\xfe\x7f\xcc\xfd}x\x1c\xc5\x95/\x8e" + - "WM\x8f4\x92myf4#\xbf\xc50\x86@b" + - "{\x0dk\xc961\x0e\x8e\xd0\x9b\xb1\x8c\x8c%\x8dl" + - "\xb0c6\xb4fJ\xa3\xb6{\xba\xc7\xdd=\xb2\xc4\x9a" + - "\x18\x08$\x86\x85\x0d8\x86\x00\x81\x1b`!\x0b,$" + - "@ \x0b\\\xb3\x0b\x04\xee\x9a\x04\x12H \x0b\x04\x16" + - "H \x01\x027\xb0\x0b\x09$@\xff\x9es\xaa\xba\xab" + - "f4\xb2\xc9\xee\xef>\xcf\xf7/i\xce\xa9~\xab\xae" + - "\xae:u^>\x1f\x99\x0f\xa15\xf2\xc9\xe6U|." + - "\x99\x0f\x11\x9d&\x0a\xd4\xf1<\x98\xf8\xf0.\xe6aL" + - "\x17\x05\xea\xe8\x94~\x1b\xe4\x1fb\x1e\x86\xa8)\xf9\x00" + - "\xcf\xff~\x98(\x11\x13E%\x14Kb\xa2\xf0q'" + - "4\x81nv\xaa\x91\xf7\x08\x1dU\xc8\x1cls\xa2\x1a" + - "s?W[\xa8P\x8df\xccZM\xcc\x8a&N\xad" + - "&\x8e\xda\xe4`\xd5r\x82@d\x93NbjZ=" + - "\xee\xd66\x8c\x8c\x90v\x97y\xdd\xacPitm\xd2" + - "MR\x01\xc4\x1f\x9c\x1f\xec\xf8\x0a\x14\x0b\xce\xddS}" + - "v\x85\xbd\xa7\xc2Qm1o\x13\xa9\x00\xeb\xcf\xe4+" + - "\x1e\xa4\x16\x02n(\xcb\xb0\x8am\x84\xa3\xef\xc4\xfd\x10" + - "\x89{*\xf0I \xa6 \x1d\xe4\xf8\xbb\x07\xc7\xdc\x90" + - "\x96LV\x97\xe5\x80QJ\xfd\xae\xff\xf5\xef?\x89\xfc" + - "\xe4\x9a\xd7H\x92v\xee\xce\xea^\xaf5b\x1f\xaa\x0a" + - "\xf5Ha%vGh\xdc\x18\xb2w\x86\xe4\xcb\xee\x98" + - "\xe2\x96\x0e\xcf\\\x95\xecxh E\x98\x8d'\xa7\x92" + - "s\x0c\xc9\xd5\xab0^\x8f9\x04Q4Xi]\xf2" + - "\xe8U\x98J~\xd8\xba\x00_r\xa71b\xb4\xe7\x98" + - "i\xb6\x9d\x84\x7f\x96\xf1?\xcb\xf9\x9f\x15'\xf9\xcc\x1b" + - "e\x8e\xc5<5K;6U\xa22\xe6\xa6\x1e\x1b\x1a" + - "\x7fU\xd9\xc2\xdd\xd5\x00\"\xd0e'jt\xa0O\xb1" + - "\xac{;\x15\xd0\xca \xb8\xaf\x82V\x06\x14\xdbaV" + - "\xb3p\x10\x1c*\xa3\xf6\xe0\x90\xb95\xb8y\x83g\x8a" + - "1\xcb\xab\xba\xf16q\xe3[\x95\x1b\xdf|\xa40\xc8" + - "\xd5he\x9b\xac\x7f\x15\xc5\xbf\x95\x99$1W\x92\x07" + - "\x07\xf95\x955/\x87\x80\x90Tb\x11\x88}\x1b\xe4" + - "\xdeU\xb2\xd9\x08$\xb2J\x88\x1c\x9e\x97\x9a\xbc\xf8L" + - "B\x06.\xe2\xc07H|\x12#$y\xe3^\xb5\xf4" + - "\x94g\x80&\xef\xd8&\xc13\xe3\x85\x9c7.=\x14" + - "\x1cx\xb5\x93\x96\x0d3\x0f\x1f\x06\x96u\x9b\x9d\x99\x87" + - "\x9e\x9e\xbb\xe8cIY\x89\xad\xb2\xa4\x9d\xf3#\xc9/" + - "\xe0\xf1_~\xed\xa6o|~ \xa4\xb8\x0e\x00,i" + - "\x00\xe7Ju\x9a\xf0ol\xf9\xc3\x0d\xd9\xd3\xff|u" + - "p>\xc3v;\xe1\x82\x04\x01Ei\xc2?{\xe3\xb7" + - "?\xbd\xf0\xf3_~\xf6\xe0X\xb9\x0a\x91}\xe6\xd8\xe0" + - "\x0b\x12\xd0\x9bg\xe2\x17\xb4\x91\x83m\x0e\xdc\x82\xdf\xcc" + - "\xc0s\xf8\xcdl|\x0e\xc167\x9f\x8b_\xd7\xc6a" + - "\xfc\xba\x06\xce$\xc4\x1f6\x0a\x9d\xf6x\x9fM\xda]" + - "\xd7d\xae\xeb\x8f\x94Msm\xcf\xa6.\x12*\xd7\xf6" + - "\xd0M]*\xe9Y\xf0\x84\x11x\xc2\xb5m\xc7-W" + - "\xd9\xa9\xe0\xf8>\xdbu#p\xb6.\xd3(U(\x1d" + - "\xdb\xf2\xba{\xfa#\xc1G\xb5\x83se\xad\x8d\xb5\x1d" + - "\xb7\xdc7\x8d1\xe6z\x0e#\xedz\x11N;E." + - "R5\xb5{\x97\xa8\xcb:\xb6\x8f\xe5\xd0\x91\xd3ek" + - "y6\x19\x93\x94cA\xad\xe7U*\xbd\xbc\x9bz\x06" + - "\xb1\x9b\xb0t\xa5>\xb9z\x1dv\xd3\xf1\xeb\x08\xd9m" + - "\xd9\x9c\x9f\xca\xf5\xca##=\x8eC4\xdb\xf1Gl" + - "\xa7\x88\xdc\x12\xd4\xf1\xf5\xdc\xf6\x90\xcep\xd8\xf0Z\x03" + - "\xf9\xb0\xe1-\x0d\xfe\xcf9\xb9\xb0\x8des\x08]u" + - "2\xd2\xa6\x0a\xc7\xc7\x0c\xdb\x1aHP\xea?{\xfc\x0d" + - "\x0f\\0\xeb\xf1\x1bHr\xeeb\x09\x1b\x94l\x19\xf4" + - "G\xae~b\xf4\xc6i\xd6\x0fH\xb2\xe5L\xbfg\xda" + - "\xaf\xccy\xeb\xde\xfc>I\xb6\xac\x8b\xf7\xe9\x16\xf3\x03" + - "\xa4^B-?\x08\xec\x93v\xc3\xcb\x1a\x05\xcb_\x1f" + - "\xf0W!\xd6\xa9$\xc7\xbe\xbe\xa2& \xd8\xe0\x1aX" + - "\xa3\x10r+\x88\x09\"U\xc6D\x17\x99\xbb\x13$\x9d" + - "\x9f\x83.\x98\xb3\x03\xca\x850\xe9\xfc\x02l/\x93t" + - "\x02r\xec\xcb\xb0\xe4@&\xd2\x04\xfb\xdb\xeb\xb0b\"" + - "D\xd6\x0c\xf7\xb77#\xba\x9bL\xa4\x09\xf6\xb7w\xa3" + - "K\xe8\xf6\x10B\xb3\xf1l\xbe\xbf}\x14}K\x07@" + - "\xfe\x14\xba\x8aD\x05\xf2\x93\x98`\xf3\x04\xc8\x9fW\xc9" + - "\xb1\x9f\xc5\x84\x9cg@\xfeJ\x90\xc0\x03f\xe1\xcb\xf8" + - "\\/\x059\x03~Qt\"\xedw\x8c\xa2\xeeL\x0c" + - "\xc5\xd8x\x05;\x09\xd7r\xf3\\w2\x13C5\xf5" + - "!w\x8f\xe20\x0a^\x0f.\x92\x93\x0fY\x1ff\x80" + - "\xc9T\x1bq\x16\x1a\xa0TRi\x0ayF\x91\x81\x98" + - "d\x10\xber\x92\x9c\xa2xh\xa2\x147r2L\x91" + - "\x01\xf3P\x99\xe7\xc2\x91\x18\x94\x86\x8e\xda;\xd7\x94M" + - "s\x12\x0bR5\x03\x94[5\xfah\\\x8e\xdd\xd0\x83" + - "\x8d4\x91e\x12\x1fc\xea\xdc\x1a\x0e\xeb*\xeb\xa2\xfe" + - "\x10i\x81\xc7vX\x1e\xb3,=[.1g\xccp" + - "\xedv\xee\xa5\xfe\xb2\xfb.\xcc\xbc\xf1\xdb" + - "\xff\xf8;\x92l\xbd\xc5\xff\xdd\xee\x9f<1o\xcf\x15" + - "\xbf \xc9\x15[\xfc\xfb\xff\xb4\xf5\xae\xefo\xcb?I" + - "\x92+\xd6\xf9O\xcd\xff\xce\xcf\x9e=\xa9\xed\x16\xac\x1b" + - "=\xfa\xe2\xe7\xf7\xbfp\xe3\xb4\xaf\x92\xe4\x8a[\xfc\x0d" + - "{\x0a\xc7\x96\x1e\xf8\xc2\x9fI\xf2\xf8\xc5\xfey=c" + - "[\xbe\xbf\xff\x89}$\xb9bU\xc8\xcbA7\xb5\xa9" + - "\xb6o\x18}\xd36-\xf3\x83\xe0\x07\x98tAU\xbc" + - "\x16\x94\xc5c\x88\x82G(X\xde\xc8yq\xc3\xb6\xdc" + - "8,\x0e\xed\x9cz\xaf\xa2\x92\xa7\xb3\xa2\x92'\xc8\x93" + - "\xba\x03\xd3\xffd%\x8f\x16\x09*y\x9c\x8aJ\x9eh" + - "$\xa8\xe4\x01\x13\xe5\x01\x90?\x16\xe1\xe0&0\x1a\x1e" + - "\xc5\xd3\x1c\x00\xf1SA\xa1\x0d\x0c\x87'\xd1q\xf5\x04" + - "\xc8\x9fG\xc7\x9e\xb0\xbc\x9e\xc5\xf6\xcf\x80\xfc\x15t\xe0" + - "\x09\xcb\xebet\x80I\x07U\x93\xb0\xbc\x14\x07U4" + - "\xa8\xa8iD\x87\x93C\xc8\xa0\x06\xa3\x10\x1d\xf9Ar" + - "$:\x99\xe7\x80|9:\xc9E`\xa1\x15\xb1P\x96" + - "\x86\x055)\x11X\xe8E'|7\xc8\xfb1P " + - "\x02\x0b\xeb\xb1@\xa6\x0f\xe4\xa3\x18\x10\x10\x81\x05\x86\xf2" + - "<\xc8\xcf\x0e\x02)X\xed\x87\x00\x902\xc0R?\x9d" + - "\xfb\xe3.\xd0\xceT\x03)t\x0e\xa5\xfe\xc7WO\\" + - "j\x1c\xf9\x95\x97H\xeaR\x0c\x144\xcf\xe0A\x85\xb3" + - "\xd0q>\x1e\x06]f4\xf1\x84\xaaK\xf1\x9a2\xb8" + - "Bc<\xb0p%\xcae\x10%\x9d\xe4\xbe\xbb\xeb\xb0" + - "\x18H\x06Kf\xc5\xd1G\xb7\xecfm\x1a\xad\x88f" + - "\xb4$xD@\x01\xa8yX\x8b\xd0\xd6\x18L\x15\x9f" + - "\xc2\x90\xc3\x91j\xc8aR\x0e1\xfe\xee\xc0}G\xa5" + - "\xac\xdb\xb1I\xa6\x84\x14=\xaaEX#\xdf8\xac\xa4" + - "\xc55\xee\xec\xef\xd6=\x9d\xf9\xee\x8f\x7f8\x15,q" + - "\xb5>\\\xd9\x0fz45l\x0b\xbd\\5\xda\x98\x82" + - "\x02\x88\xa8e\xb6j\xa3\x99j\xa3L\xbfc\x0f\xbb\xb5" + - "\x88>{\xf2\x85C\x9c\x83\xe9y\xb7\xbb\xa7\x9f\x06\xfb" + - "S\xd94\x9cjx\xd3x\x91y\xb0\xaf\x0f\xe7\x99\xea" + - "[\x8dg\xbd\xfc\xd47QS\x8b.\xcb\x9eqFs" + - "e\xe8m\x9e[\xa3\xb8\x03q\"!\xed8y\xb8a" + - "\xe2\xf7$*\x1fw\xd32y\xdb\xe1\xa4(\x9ep\x12" + - "\x04uu_\x8b\xe1\xd3C\xe2\xc8\x0d\x12\x86\x14\xc4\xf4" + - "F4\x84\x92\x0eg\xd4J\x0a\xa9~\xcd\xd4-\x8b9" + - "Y\xdb\xc4GP\xdcg\xf0^?\xbe\xf5\xae\xef\xdc\xf8" + - "\xe6\x8f\xce\x0b\x90\xa9\xf5\x9c\xb8\x89p\xe6\xe5\x8a\xd8\xb0" + - "Q8\x84\x13\xe9\x14}\x0c\xb1\xe5\x8e\x0d\xa0\xe4\x02|" + - "\x10\xc5\xab\xb9\xae\x16\xbd\xc7\xa0\xac\xeb\x84\xbb6\xbcr" + - "^-\xb5\x09\xa9\xd1*<\xb75\x97\xa3\x0d\x16\xbe\xce" + - "1,\xf9D7\xab\xf6\xe7\x9d\x99\xc5W\xbes)I" + - "\xd2A\x1f\x15\xa7\x80\xe9\x87Tub\xa6?\x1aWZ" + - "\xac\xf7_\xa2\x16\xc2,\xc2\x8c\x09ia\x07\x850\xc7" + - "`\xc2\x84d\xa5\xd3\x9a\xf9L\xdf\x8a\xf2% _\x89" + - "\x0b\x7f\x8aO\xf5+\xb0\xcaDa\xabK\xf3\xa9~5" + - "\xca\x15<\x81\x16>\xd5\xf7\xa0\x05\xaf\xe0\x09\xcc\xe2S" + - "}U\xe2E\xb2a6\x9f\xea7\xa3\\\xe2\x09L\x9b" + - "\xc3\xa7z\x1d7\xe5\x12\xbc\xbdq.\x9f\xeb\x8b\x98h" + - "\x1f\xfa\x0ex\xd5s\\\xf6\x94 ,\xe4Iba9" + - "\xa1e#ta\xf8{\xa7\xee\xe0\xceUB0\"\xbf" + - "\xb7Nb\xcaQ\xbek\x8fx\x93\xa5F\xb1\xc8\xf2\x86" + - "\xeeQ\x06\xbaa\xb3\"\x19\xc7\xe1\x10I\x15\xfe}A" + - "PN\xa8\xcc\xea\xb0\xc7\x18OV\x0b\xca\xde\xe2\x86\xa5" + - "\x9b5\xd4\xfc38\x14\x9aN\x0dn\xce\x8a\x88\x9cR" + - "[\xb2E$E\xec\x92\x9e\xf9\x89A\xc5=\x1a\x89\x08" + - "\xf7\xe8\xb0 \xb0\xbdZ\xd8\x86`+_\xe9\x08\xb4\xbe" + - "\xbb\x90\xbc\xc1)\xad\xd7=\x87h\xc6\xf8\xc1\xd8$\x83" + - "B\xcf\xb0}\xcc\x18o\xab> Tf\x8c\xf1N\xa3" + - "0\x95\xfdV\xf9\xd8\xfd\xcc1J\xa3\xd0AJ\xce\xb8" + - "\x92\x8b^\xcf\xf7\x02M\xdb\x14f\xad\xb2;\xccA\x9c" + - "x\xda|\xdc\xdfy\xc5\x92\xef\x7fe\xc5\x9e\x9b\xc8A" + - "\xabx\xbaL;\x96\xdb\x1ed\xc3 \xb0\xf8%s\x0f" + - "\xbf\xe5\x83\x95\x7fw\x19I.\xdaB\"\x01sz\x8b" + - "#\xb8\xb5\x16T\x979LEvq0f\x1d|\xae" + - "Mm\xc7\xe2\xaf\x8c\x13\x18\xfb\xaa\x8b\xed\xdc =i" + - "\\u\xb1\x95\x11\xd6c< &\x08sH.E\x9f" + - "\xd3%\xa1\x0f,\xd8\xd7\xdf\x8c\xe7Az\x99\x87\x83}" + - "=\xd8\x02\xb8\xaf\x97,2\x81\x8b\xedQ\xfc\xfa\xa5\x0b" + - ",p\xb1=\x89\xa7\x97.\xb0\xc0\xc5\xf6,\xba\xde\xa4" + - "\x0b,p\xb1\xbd\x8c\xae1t\x81\xbdI\x95\x14\x92\xd7" + - "Q.\x19\xd4gP\xea\xbf\xbe\xe5\xdc\xd4\xe5\xdf\xfe\xc6" + - "s$\xf5\x0e\xe6\x92M\x8b\x05\x0c5\x83\x15%<\xd3" + - "\x1b\x02\x86\x9a\x0avv,3\xd9\xe0\x18\x98D\xc7q" + - "\xd3\xab\x06Yu\x83\xac6y#\x01m\xfam\xd7\x10" + - "\xcb\xdd\x14Zt( wa\xad\x06U\xbc\x7f&\x1b" + - "\xf1z&X?\x89\xa9\x01?\xa49\xeb\x99`$^" + - "\x11\x07\x84\xc6\x9d\xa6a\x91\xcc\xf6\xfeI\xcd;M\x83" + - "\xb4[\x95\x0a\xb7l\x15p\xfb\xd0\xce\xdc\x0aE\xc5\xd8" + - ",\x8d\xda\x16\xab\xe2\x1etM\xc6JS\xf0\x11\x1e\x82" + - "\x1f\xab\xdfn7'\xfauo\xb4*T\xe4\xd4\x02\x1b" + - "r$\xaeP\xb83-;\xa2\x88\xed\x92\x08\xf5\xc7\xb1" + - "\xec\xd8\xc8\x91\x8c\xc1j\x10GN\x1c\\}\xe6\xc1\xd5" + - "\x87\xc0K@\x8ep\x0c}rn\x1c\xb5\x14e\xb0\xa2" + - "\xe4$\xf8\xf2.\xae[UQr\x12T\x9a]\x8a\xa5" + - "\x13\xb2\xe4D\x80\xbdN*9\x89\x8a\xe4\x86k\xb0\x04" + - "C\x96\x90\xd4\x89\xe4\x86\x9b\x11\xf0[\x96\x90\xd4\x8b\xe4" + - "\x86;\xb0\x94C\x96\x90\x086\xed\xd4\xbdu\x0f\x819" + - "\x0f\xf2\x03u\x0al\xd8#\x08(.KE\x1a5\xfe" + - "\xe9=\x8erY*2-\xcd\x17\xde\xeaR\x91\xe9Q" + - "\xbe\xc9z\x01\x0b<\x9e\x07\xf9kAI\x0bl\xb2^" + - "\xc5\xe7}\x05\xe4o\x83\xbc\x89\xd3F\xa6\xde\xaa\xbb\x8f" + - "\x90\xec\xdb \xff\xb0NT\x9a\xc1\xe7\xfaA\xdd\xf5A" + - "IHC=l\xca\x04)J\x1d\xa6\xe6G\xeb5\x9a" + - "M`u\x81(]i\xaa\xff\x15!\xd94\xc8\x17\xd4" + - "\x0bX\xf8$!\xa9\xc3\xb0JAV\x8447\xf3\x8d" + - "\xd6\"\xac\xb48\x0a\xe4K\xeb\x15\xb4\x84c\xf0\xfcK" + - "@\xbe\xb2^AKX\x81\xa5\x02\xcbA~b\xbd\x82" + - "\x96\xb0\x1a+BN\x04y\x1f\xc8g}\x86'U\xf4" + - "bI\x80\xac\x08\x99=\x8fo\xcc\xaa+B\xe6\xcc\xe4" + - "I\x15\x1b\xf1\xbaa\xe5Gr.\xdf\xb0\xa5N\xc7\xeb" + - "n\x05\xf9(\xc8\xe7\x89\xfd\x1a\xc3\xeb\x86\x05\x1e\xc9O" + - "}\x96o\xd7v\xe0uK \xdf\x05\xf2\xf9I\x8e\xe0" + - "9\x81\xfd \xcb;\x0ek\xe6\x99]\xe7\xd7\xff\x8c\x90" + - "\xecE \xbf\x02K \x8e\xe3\x99]\x97\xe1\xfd\xc8\xea" + - "\x8e\xcc\xe7xf\xd75x~Y\xdd\xb1\xa0\x8fgv" + - "\xdd\x88\xe7\x09\xab8\x92G\xac\xe7\x00\x9ewc\xc9\xc4" + - "= \x7f\x18+r\xd2X\x01\xb3\xec\xc1z\xdc\x88\xca" + - "\x9a\x8cO\xb7`\x09\xcc\xb2\xa7\xeb\x87A\xf1\x0a(\xde" + - "\xc6\x92\x96Y\xbc\x04\xe6\xad\xfa7\x08\xc9\xbe[\xaf\xd1" + - "\xc1X\x84&\x8f\x9e\x8d\xc8\x9e\xcb>\xaa\xef\x84\xf6\x0d" + - "1\x8df\xd3\xa0\xf8\xcc\x1c^\x1a\x93\x8cA\xfb9 " + - "?\x0a\xe4\x9f\x9d\x8b\xa51\xcb\x8e\x88\xe1\x01K@\xb1" + - "\x12\x14\x0b\xe7\xf1\xd2\x98\x15x\xc0\x09 _\x0b\xf2E" + - "\x9f\xc2\xca\x98e=\xfc\x80~Pl\x05\xc5\xe2\xf9\xbc" + - "4f3\x1ep\x06\xc8M\x90\xff\xd5aX\x19\xb3\xcc" + - "\xe0\x07x\xa08\x1b\xcb>\x0e\xe7\xa51g\xe1\x01\xe7" + - "\x81\xfc\x12\x90\x1f\x93\xc1\xd2\x98e\x17\xf3\x03\xae\x00\xc5" + - "\x0d\xa08\xb6\x9e\xd7\xc6\\\x17\xc3m<\xc8o\x05\xf9" + - "_/\xe0\xa517\xc7\xe0+\xbb\x09\xe4w\x81|\xe9" + - "\x11\xbc4\xe6\x8e\x18,\xb8\xb7\x83|?\xc8[\x8f\xe4" + - "\x951\xf7b\xbd\xc9= \x7f\x18\xe4m\x9f\xe64\x02" + - "\x0f\xa2\xfc\x01\x90?\x16\x8b *\xc6\x9a.\xbb\xac\x1a" + - "\xa7\xed#\x95\xf5\x7f\xa3\xba{R\xc9=\x95\x11\x8dm" + - "\x0f\x0d\xe8j e\xdeh\xbdAM\xd3\xc0\xcc<-" + - "\xef\x86Fk\x014\xa6iP\x9e\xb3\xe7J\xbf\x81\xc8" + - "K\xe8$1\xb50\xa2Prq\xde\x8d\x80.\xc0\xd0" + - "\xb0\xbc\x092\xa9\x05i\xe7i\x15a^\x1d\xdc\x87i" + - "[:iw\xdd\xcdL\xc9\x88\x16n\xeb\xcd$\x06\xd2" + - "I\xcd3\xae\xdb\xadOT\xb7\xeeFD\x0d\xf5\x19A" + - "N]\xfe8n;\x7f\x9c\xea\xa3\xd6SC\xf4\x02\xa2" + - "J\x87\xcf\xca\xb5C\x14\x1e\xd8\xd0\x95\x0a\x11\xa1\xe9\x8a" + - "\xc0#\xa9\xcf\\\x81\x1b\x12\xb4\xa2\xd0\x0a\x1e[\x93\xcf" + - "\xbd{8_\xf9>\x86\xf3Su\xf9p\xbeV\x97\x0f" + - "\xe7\x0f\xd5\xe5A\x8b\xea.\xdf]\xd0\xcd\x8aK\x17t" + - "s\xaa\xb7\xad\x9b\xb5\xde\xb6n\x1e\xeam\x8b\x16\x93\xde" + - "v\x0e\xa4k\x1cF\x11Zf\xa2\xd3\xd0\x94\xf3\x06\xca" + - "\x08W\xca3K\xdc\x95\x10\x95\x86N\x08@\xbe\xf0\xd4" + - "\x85\x92\xdb\xc7\xf4R\x96\x04/\xb9Z\x11\xe1\xf2\x8a\xd3" + - "V\xb7\xa1\xbc\x8d\xc02Q\xd5C\xf6I\xa6\xad\xe1x" + - "\x10\xc3a}0h\x90\x8dN\x1d\xe9\xd86:U\xdb" + - "\xdac\x05\x8e\xea\xcc\xbb\x91\xea#\xe2\xf8,\xd5\xcd\xa2" + - "\x07;q\xf5(\xc0\xdb9\xc4\x89\x83f\x9f\xfc\xc4\xfc" + - "9u\xf3\x93\xdc\xf1I\xba\xf9\x17\x9cX7?\xc9\x1d" + - "\x07\xcd\xfe\xc2\x13\x7f\x82>\x16\xcd>\xf9\x89Guw" + - "\xd0\xcb\x89\xaa\xb7\xd0\x171\xe1z\xac8\xe8\x91Ln" + - "H\x01\\\xf6\xf9d\xbda\x84\xc4\xb1Z=\x10\x9b\xa5" + - "\xe2\xa0\x97\x0b\x88$C\xa7\x1b\xb7f]\x12c\xde\xe4" + - "\xec\xdeC\xfb\x14\x14\"\xd9\x9a\xb4h\x9d\x1c\xf1\xd4A" + - "8\x1cN\xf2F\xb0\x82\xc3\xcf\x893\xa1S\xd1\xe0\xd8" + - "\xcf>\xec?\xb0MF\xf7\x0c\xab0\x15\xdb~H\x16" + - "\xadP-TD.\x1d\x1e\xb9\xbc\x8aG.\xaf'$" + - "f\x8f\x8c\xf8%\x87\xe1\xa1$\x83\x07Wq\xef:\x9e" + - "\xa1Y\x05U\xb8\xc6\xb0\x0cw4\xa6\xdeHt\xaa<" + - "\xa1\x00Q\x9f\xe2\xdd\x98h\xe0\xaf\xa6\x08\xc3\x9dZM" + - "\xef\x83\xfbI\xad\xa6{\xe1\x86\xc4\xdf\xa8\xf8['\xfe" + - "\xd6\xa7V\xd37\x08\xa1\xb1T\x07}\x88\x10\xda\x90\xea" + - "\xa0\xd7\x13B\x1bS\x1d\xb0u\xa7\xd3\xc4\xdf\xe9\xe2\xef" + - "\x0c\xf1\xb7I\xfc\x9d\x99\xea\xa0\xb7\x10B\xe3\xa9\x0e\xbc" + - "n\"\xd5\x81\xe7M\x8a\xbf\xcd\xe2o*\xd5\x81\xf7\x93" + - "Nu\xd0\x1f\x11B[R=(\x9f%\xfe\xce\xe6\x1e" + - ";:\x87#\x81\xd2\xb9\xe2\xf7\xbcT\x0f\xbd\x93\x10\xdf" + - "a\xa6>\xb1^7\xe9H\xd9\x12D\xdd~\xd9*\xbb" + - ",\xdfkQ\x8e\x9e\xed\xadm\xd7\xad\xbc\xc9\xf2!\x9e" + - "6\xf5\x06u\x8fu\xe9\x16m\xad!k\xab![V" + - "%\x1b\xd2st4\x94EPvR\xd1\xd4-5v" + - "\x16\xa8\xa3\xa8\xee\x15\xbf<\x97\x04\x0a\x94gKF\xac" + - "\xbb\xa8W] [2\xb4.\xb7J\xb8Qw4\xaf" + - "\xb5\x96\xb0\xad\x96pY-\xe1\x8a\xc9\xc2\xb87\xf9\xfa" + - "\x1b\xddaB\xaa\x1f\xda(N\xea0\x90-\xf3\x1dV" + - "0\xb0\"\xb0\xdb\x18cN\x81Y\xd4\xabjw\xb2i" + - "\xb4[\xac\xd72\xbc\xaa^\xeb\x0a\xcc\x85\x1c\xabq\xc1" + - "\x1c\xdd^%\xeb\x19\xf7\xa81\xb9\xb3&\x1d\x8b\x0f\xfb" + - "9\xdf5\x1cfU\x8d\x8f\x00\xa8\x9dz}\xb6]:" + - "U\xf72\xb9\xd1\xbc=\xd5g5$\xc0g\xcccC" + - "8\x1c\x05\x00\xbc\xb3\x82\x0a~\x9d$\xf7\x8eo+\xb1" + - "\x82\xbf\x9dM`\x80a\xea$8\xc5IX\x8b=q" + - "P2\xdc\x86.\x89\xf3;\x85\xef\xf3\"\xc5%qA" + - "\xa7\x92/\x1a0\xb5\\<,\xf2E\xaf\x10\x04\xb9\xff" + - "\xfc\xce{g\xc7\xee\xf9\xe3\x01\x92\xbcl\x0b\x89\x1c\x1c" + - "\xad\xff\x90\x0c\x03\x01\x15\x17\x89\x0d\x96$\x0c}M\xc2" + - "\xc2\xfaO\x80L\xa9\xcc\xe6\x92\x89V\x09o\xec\x954" + - "AaW\xacX\xa5\x847\x82I\x9c\xb2<\xc7\x9d\xa4" + - "!YW\xbb]\x89\x962\x15\x13\xae\xa5\x17\xb8W\x93" + - "r\x16\x9f7\x8c\xf3J?\x1b\xba\xea\xab$I\xb7\xf9" + - "\x02\xae\x9a\x93\x02\xfd\xb32" + - "\xf0\x16\x9e\xe7\xa0\x18\xb9<\xdb5\xcc@Q\xb8i\x8e" + - "T\xb9i\xc4\xb3_\xb3X\xe5\xa6\x11\xc3\xe0\xbaU\x92" + - "\x1a3\xc8@\xb9\xf1*5A8R\x8br_\x13\xdc" + - "4\xabd\xd6p\xcc\xc8\x8f\xd3\x84\xff\xe1\x8a\xd9C\xbf" + - "\xde\xf7\xf3\x0b\x02\xd2U\x95\xa0\xa9}\x94\xe9y\xe6\x84" + - "\xa1\xb9\xb2e\x8c\xe3\xea\xefzz\xb1t\x8ani\xd2" + - "\x8f\x9c\xd9i\xe4\xbd\x90\xb9\xac}\x94!\x17\xea\xc1+" + - "xj\x80\x9a\xc7\xb7\xd8\x16\xfb\x04\x9cR\x8be,\xac" + - "\x02y6\xee\xb1b\xe9\x10\xfe\xc25\x18-\xae\xc8\xd8" + - "\xa6\xf9\x81\xa5Z4!`\xd9:\xd0\xbd,\xabzi" + - "=\xf7}\xf5b\x86\xa5\x0c.Ef\xd6\x0e.i\x02" + - "\xf8s3\x06\x91\xc2\xe2],\x80A\x18`\x0cv\xc9" + - "\xc4\xd4:\xe1\xb32P.\x83N\xf5\xa2j\xb8\x88\xf2" + - "\x901\x18\x0b`f\"a\xf0\xb0J\x18\x9cl\xd0\xb8" + - "oj\x02\xdd\xe6\xd2\xfb\xde\x18\xe5\xbe)\x85\x14\xf8\xd6" + - " s\xb4\xb9\x92\xdc\xfdata\xc7\xb9o\xeaAt" + - "\xa7\x87\xeew\x1eK\xedc\x16\x89\x15\xbc\xd10\x89\xbf" + - "`\xda\xc3\xbay\x92\x8e\x88\x0e\x81\x10\x9b\x863\xcfG" + - "\xdfx\xf9\xb4\xf3\x9bv\xffC\x98\x1f\xc9\xb3\xcf\xbb\xa8" + - "^\xc2j\x10\x16w\xcb\xa6G\x13\xfe\xda\x05\x87=|" + - "\xdf\xef\x7f\xb8?\xe092\x99\xe5\xf6\xdb!X/\xfe" + - "\xce\xeaa\xca'\xfe\xeeq\x1c\xc5?m\xb9CN\x99" + - "\x91\x18\x1c\x15n\xb3\xec\\\xd9\xdd\x84\xe8\xf6\xc1'\xab" + - "\x05\x1eqPu\xd9\x16\xa1!\xb0d}@N7\xaa" + - ";%\x8b\xb9\xa4\xdd\xcd\xe6l',\x17\x88\x05\xc1o" + - "\x96\xb3\xc7\x98#\xa6\x8bI5\x0d\xd1C\xd5\x18S\x8c" + - "\xa5,\x08\xc7\xf9\x930\x99?\xa1\xd1\x81\xe7\xe58\x7f" + - "\xf6B\x99GFc\x94\xfa{vu\xc4\x7f|\xc7\x0f" + - "\xef%\xc9\xf7\xb6\x90\x08zw\xe1\xc3~\x19\x8e}I" + - "\xd0Dh<\x1a\x92\xfc\xe0\x16\x95&\"z6\x1f\xac" + - "u\x18\x9a\x91@\xefu\x8d\xdc!\x9b\xc4\x10\x8c\xe4w" + - "\xa8\x9f\xc6\x07\xf1\\\xcc\xa2\x0es(\x05\xc6B\xbe*" + - "^\xc0\xa1\x05\xfa\x1d\x8a\xb9A\xb8\x0e\x1f\x94\xe9\x96\xb7" + - "\x17\x09\xa2\x93Z\x8aT#Z\x91kD\x132\xd7I" + - "\x04\xf7Gu'\xdf\xe9\xe8\xdb\xc3\x86\x9a\x02\xccQi" + - "p{\x8c\xd0\xb8\xff\xb3\x9f\xdf\xf9\xc7\x93\xf7~\xeeq" + - "\x19\xe7\x0f\xdb\xf0\x04s\xcc\xf9\x88\xfbc\xc9\xc2\xc7\x0f" + - ">0\xfd\x9a\x83G\xe5z\xc6\x98\x86\xf5(\xd9|D" + - "\xe6>%\xb0:/\xa1\xd1\xec=\x89\x08m\x8a\xf8>" + - "\xf7\xcc\xdf\x9d\x80\xaf\xf2.P<\x00\x8aE\x1f\xfb\xdc" + - "5\x7f\x7f\xe2N\xf8\xcc@\xf1\x18(\xf6~\xe4\xf3y" + - "\xe8\xd1\xc4^B\xb2\x8f\x81\xe2\x19P\x18\x1f\x0a\x96\xf2" + - "\xa7\xf1\x88g@\xf1J\"\xa0\x10\x87\x19\xea\xe5\xc4\x91" + - "\x84d\x9f\x07\xc5\xfb\xa08\xfeO\x82\xa5\xfc=\xbc\xab" + - "w\x13\x1a\x1dLFhS\xfd\x07\x82\xa4\xfc\xa3\x04\x12" + - "3\xc1\x01\x0d\xa0\xd8\xf6\xbe/\x10\xe2\x92\xf0\xda\x1b\x92" + - "\x1a\xcd\x1e\x05\x8a\xe1?\x0a\x96\xf2#\x92m0\x1e@" + - "\xb1\x10\x14\xe7\xfe\xc1\xe7\x1e\xfa\xa3\x930\xb0\x16\x82b" + - "9(\xbe\xf6\x9e\xa0/oM\xdeGHv9(\xfa" + - "Aq\xfe\xbb\x82\xbe|}\x12\xe6\xc7~Pl\x05E" + - "\xfc\xbf|>\xe1mN\xc2D{\x1a(\xf2\xa0\x18\xfd" + - "O\x9f\xcfxz\xf2B\x98!AQ\x02\xc5\x92w|" + - "\xee\xa6/\xe2\xed\x96@\xb1\x0b\x14\x17\xbd\xed\x8b\xb9\x10" + - "\xaf\xb1\x0b\x14W\x80\"\xf9{_`\x9f'aR\xbd" + - "\x04\x14\xb7\x82\xe2\xf3\xff\xd7\x17\xb3!^\xfc&P\xdc" + - "\x05\x8a\xe6\xb7|>\x1d\xde\x91\x84/\xe4vP\xec\x07" + - "\xc5\x8a7}\xee\xab\xbf\x17\x9f|?(\x0e\x80b\xfe" + - "\xef|\xee\xac\x7f$\x09\xbd\xfe0(\x9e\x00E\xea\x0d" + - "\x9f{\xeb\x1fO\" \x16(\x9e\x01E\xfau\x9f\xbb" + - "\xeb\x9f\xc6\x8b?\x05\x8a\x97@1\xeb5\x9f\xfb\xeb_" + - "\xc0'\x7f\x09\x14o\x82b\xfbo}\xee\xb0\x7f\x1d{" + - "\xf7MP\xbc\x0f\x0a\xf37>\xf7\xd8\xbf\x87\x8a\xf7A" + - "\x91n\x8e\xd0\xa63_\xf5\xb9\xcb>\xd9\x0c}\x95n" + - "\xd6hv\x01(\x8a\xaf\xf8\xdcg\x7fX3\xc6.@" + - "q\x02(\xac_\xfb\xdci\x7f<*N\x00\xc5i\xa0" + - "\xf0~\xe5s\xaf\xfd\xc6f\x18\x88\xa7\x81\"\x0f\x8ay" + - "/\xfb\xdcm\xaf7\xc3\x03\x9e\x01\x0a\x13\x14\xe5\x97|" + - "\xee\xb77\xf0T&(\xc6A\xf1\xb9\x17}\xee\xb8/" + - "7#\x97\x1b(v\x81b\xce\x7f\xf8\x1c\xbbj\xa2\x19" + - "q\x07@q\x1e(V\xbe\xe0s\xf0\xaas\x9a\x11T" + - "\x15\x14{@\x91\x7f\xde\xe7\x9e\xfb\xf3\x9b\x11B\x0a\x14" + - "\xfb@\xc1~\xe9sV\xaeK\x9b\xff\x93\x90\xec\x15\xa0" + - "\xb8\x01\x14c\xcf\xf9\x82\xfc\x17\xbb\xe4\x06P\xdc\x0e\x8a" + - "\xb9\xcf\xfa\x1c\xd7\xea6|\x8e[Aq\x0f(v<" + - "\xe3s\xe7\xfd\xdd\xcd\xcf\xc1;\x07\xc5\x01P8\xff\xee" + - "s\\\xabG\x9a\x7f\x04\xaf\x16\x14\xcf\x80\xc2\xfd\x85\xcf" + - "\xbd\xf7Oc_=\x03\x8aW@\xb1\xf3i\x9f\x03[" + - "\xbd\xdc\xfc\x10!\xd9W\x9a5:\x98\x8a\xd0\xa6\xf1\xa7" + - "|\xee\xbd\xff\xa8\xf9\x0dB\xb2\xd1\x94F\xb3\x09P\x14" + - "~\xeesd\xab\xa6\x14\xc6\x9e@\xb1\x00\x14\x13?\xf3" + - "\xd1}\xbf\xec\xb0T\x84\x12\x92=\x0a4KA\xf3\xb7" + - "O\xfa\xdc\x81\x7fL\x0a\xeej9(\xfaA\xf1\xa9'" + - "|\xee\xc1_\x9f\x82'\xef\x07\xc5VP\xec\xfa\xa9\xcf" + - "]\xf8\x9bS\xf0\xa2\xb6\x82b\x14\x14\xf6O|\xee\xc3" + - "gxu\x13\x14\xe3\xa0\x18y\xdcG.\xe0e\xe5\xd4" + - "*\xb8\xfa\xd9\xa0\xb9\x084\x9d\x8f\xf9\x9c\x0d\xf8\x82\x14" + - "\x18\x12{@\xb1\x0f\x14g\xfd\xd8O\xd3\x15\xf0BR" + - "\xd0'\xfb@q-(\xbe\xfc#\x9f#h]\x83\x8a" + - "kAq+(v?\xea\xa7\xe9\xe7\xe0\xebLA\xbf" + - "\xdf\x0e\x8a\xfd\xa08\xfb\x80\xcf\xb1\xb5\xee\xc5#\xf6\x83" + - "\xe2\x00(\xce\xfb7\x9f\x83k=\x92\x82\xee=\x00\x8a" + - "\xa7@q\xce\xff\xf1\xd3t\x15!\xa9'S\xd0\xbf\xcf" + - "\x80\xe2\x15P|\xf5\x11?M?\x0f/\x04O\xf5\x0a" + - "(\xde\x06E\xf4a?MO $\xf5V\x0a!\xdb" + - "A\xf1.(\x0e\xfb\xa1\x9f\xa6\xab\x09I\xbd\x93B@" + - ".P|\x08\x8a\xd2C>G\xf0\xfa\x00O\xf5!(" + - "\x1a\xd2\x11\xda\xb4\xe0A\x9fCx\xd5\xa5\xe1\x88h\x1a" + - "^.(\xf6<\xe0s\x08\xaf\xa64\x1c\x91\x00\xc5|" + - "P|\xe5_\xfd4\xed\x80\x858\x0d\xafp\x01(\x96" + - "\x80\xe2\x88\x7f\xf19\xb8\xd7\xa24| \x0bA\xb1<" + - "\x0d\xe6j\x7f\x9avQ\x9ajM\xc3L\xbd\x04\xe4+" + - "\xe1\x80\x8b\xef\xf7\xd3\xb4\x9b\x90\xd4\x8a4\xcc\x0c+A" + - "1\x04\x8aO\xef\xf7\xd3\xb4\x07\x0cY[A1" + - "\x0a\x8aK\xef\xf3\xd3\xf4$B\x96\xb14\x8e8\x134" + - "\xe3\xa0\xf9\xbb{\xfd4]\x0b\xdfs\x1azw\x17(" + - "\xf6\x80B\xbb\xc7O\xd3^\xf8:\xd3\xf0I\x9d\x07\x8a" + - "K@\xf1W\xff\xec\xa7\xc1`M]\x9c\x86\xa1x\x09" + - "(\xae\x06\xc5g~\xe0\xa7\xe9\xc9\x84\xa4\xaeLc\x8c" + - "\x1a\x14\xd7\x82\xe2\x98\xbb\xfd4\xed\x83Q\x82\x9dx5" + - "(n\x02\xc5\xb1w\xf9i\xba\x9e\x90\xd4\x8di\x98\x01" + - "n\x02\xc5]\xa08\xee\xfb~\x9a\x9e\x02sx\x1a\x03" + - "V\xa0\xd8\x0f\x8ao\xdc\xe9\xa7\xe9\x06\x18>i\x8cS" + - "\x83\xe2\x00(f\xde\xe1\xa7i?\x0c\x9f4V\xc9\x83" + - "\xe2\x09P4\xdd\xee\xa7\xe9\x00\xcc\xe1i,\x93\x07\xc5" + - "k\xa0\xd8\xf7=?\x0d\x06v\xeaU|Qo\x82\xe2" + - "}P\\\xf6]?M\xb30#\xa7\xe1\x93z\x1f\x14" + - "\xd1\x96\x08m\xba\xfc6?M\x87\x08I\xd1\x16x!" + - "\xd1\x16\x18\x0c\xa08\xe1V?M7\xc2`h\x81\x8b" + - "\xcf\x00\xc5\x1cPt\xfd\x93\x9f\xa6\x9b\x08I\xb5\xb4\xc0" + - "\xb26\x07\x14G\x81\xa2\xfb\x16?MO\x85\xe5\x19\x8f" + - "X\x00\x8a%\xa0\xe8\xb9\xd9O\xd3\xd3`\x94\xb4\xc0\xc5" + - "\x97\x80b%(\xd6\xdc\xe4\xa7\xe9f\x18\x0d-0\xe0" + - "V\x82\xa2\x1b\x14\x7f\xfd\x8f~\x1a6:\xa9\x0e\xbcF" + - "7(\xfaA\xf1\xcd\xef\xf8i\xfaE\x983Z\xe0\x1b" + - "\x1c\x02\xc5\x19\xa0Xx\xa3\x9f\xa6[\x09I\x9d\xde\x02" + - "\xd6\xc4VP\x8c\x82\xa2\xfd\x06?MO\x879\xa3\x05" + - "S\x98AQ\x02\xc5\xe1\xff\xe0\xa7\xe9\xdf\xc0\xba\x8d\xd7" + - "(\x81b\x17(\xa6]\xef\xa7\xe9\x97`\xd6\xc7#\xc6" + - "Aq\x1e(\xa6_\xe7\xa7\xe9\x190\xeb\xb7@\xb7\x9f" + - "\x0d\x8a\x8b@1\xe3Z?Mu\x98dZ\xe0\x9d_" + - "\x04\x8a+@\xd1\xf8m?\x0d\x1b\xa4\xd4exW\xfb" + - "@q-(\x1a\xfe\x97\x9f\xa69\x18>-\x88\x1c\x08" + - "\x8a\x9b@\xf1\xf7\xd7\xf8i\x9a\x87\xe1\x83wu\x13(" + - "\xee\x02\xc5\xd7\xaf\xf6\xd3\x94\xc1\xf0i\x81W{\x0f(" + - "\x1e\x06\xc5\x17\xbe\xe5\xa7\xe9\x08l\x95Z\x90s\x02\x14" + - "\x07@\xb1\xec*?M\x0b0|\xf0\xe2\x0f\x83\xe2\x09" + - "P\\p\xa5\x9f\xa6\xa30|\xf0}<\x01\x8a\xe7A" + - "q\xc5\x15~\x9a\x1a\x84\xa4\x9e\xc5k\xbc\x04\x8a7A" + - "q\xe17\xfd4l\xc4R\xaf\xb7\xc0G\xf8&(\xde" + - "\x07\xc5)\x97\xfbi\xba\x1d\xc6\x15\xbe\xf3w[4:" + - "8+B\x9b6\\\xe6\xa7\xa9\x09\x0b\x08\xca?\x84\x03" + - "\x1a@\xd1\xbf\xcfO\xd3\"L>\xb3\xa0\xab\x1af\x81" + - "i\x00\x8a\x81o\xf8ij\x81i0\x0b7\x01\xa0\x98" + - "\x0f\x8a\xc1\xbd~\x9a\xda0\xf9\xa0b\x0e(\x8e\x02E" + - "\xf6R?MK0\xdeP\xb1\x00\x14K@1t\x89" + - "\x9f\xa6;`\xbc\xa1b!(\x96\x83b\xe3\xd7\xfd4" + - "u\xc0\x1cD\xc5RP\x9c\x00\x8aM\x7f\xef\xa7\xa9\x0b" + - "V\x06*V\x82\xa2\x1b\x14\xa7^\xec\xa7\xa9\x07\x03\x11" + - "\x15'\x82\xa2\x0f\x14K/\xf2\xd3\xb4\x0c\x1b\xf2Y\xb0" + - "\x9e\xf7\x83b+(Z\xff\xceO\xd31\x98\xaff\xc1" + - "\x1au\x06(LP\xb4]\xe8\xa7\xe9N0?fA" + - "\xe7\x96@\xb1\x0b\x14k/\xf0\xd3t\x1c\xc6\xdb\xac?" + - "\xc1\xb0\x02\xc5E\xa0\xe8\xdd\xe3\xa7\xe9\x04\x0c\xabY0" + - "\x8f]\x02\x8a\xabA\xb1\xeek~\x1a\xf6\xcb\xa9+g" + - "\xfd\x0c\x96(P\xdc\x0a\x8aK\xbe\xea\xa7\xe9\xdf\xc2\x12" + - "\x85G\xdc\x0e\x8a\xfd\xa08\xf9|?Mw\xc1\x1c3" + - "\x0b>\xf3\xfd\xa08\x00\x8a\xbe\xf3\xfc4=\x0b\x06\x09" + - "*\x0e\x80\xe2)P\xac\xff\x8a\x9f\xa6_\x86%\x0a\x15" + - "O\x81\xe2%P\xb4\x9c\xeb\xa7\xe9n0\x07ga\xd6" + - "\x19(^\x03\xc5g\xcf\xf1\xd3\xf4l\x98|f\xc1 " + - "y\x0d\x14\xef\x82\xe2\xe8\xb3\xfd4=\x07\x96\xa8Y0" + - "\xed\xbe\x0d\x8a\x0fA\x11\xdb\xed\xa7a\xcb\x97\xfa`\x16" + - "L\xa2\xef\x83\":;B\x9b\x12_\xf6\xd3\xf4+0" + - "+\xcd\xdeB\xc8\xe0l\x8dfg\x80|\xf6Y~\x9a" + - "\x9eGH\xaaq6\\b\x06(\xe6\x80\xe2\xa4]~" + - "\x9a\x9e\x0f\x93\x12\x1c\x90M\x83b\x01(\x8e\xfc[?" + - "M\xbf\x0a\x86\xe5l\xf8\x98\xe7\x83b%(V\x9f\xe9" + - "\xa7\xe9\xd7`\xee\x99\x0dK\xd4RP\xf4\x81\xe2\xb4\x09" + - "?M\xf7\xc0\x9b\xc5k\xf4\x81\xe24Pl\x1e\xf7\xd3" + - "\xf4\x02\xb08Qq\x1a(\xf2\xa0\xd8\xb2\xd3O\xd3\x0b" + - "\xc1\xe2DE\x1e\x14%P|q\xccO\xd3\xbf\x83)" + - "\x06\x15%P\xec\x02\xc5\xd6\xb2\x9f\xa6\x17\xc1+G\xc5" + - ".P\xec\x01\xc5\xe9\x9e\x9f\xa6\x17\xc3\x0a\x85\x8a=\xa0" + - "\xd8\x07\x8a\xbfq\xfd4\xfd{0WP\xb1\x0f\x14\xd7" + - "\x82\xe2K\x8e\x9f\xa6_\x87\x99d6\x8c\xd0\xabAq" + - "\x13(\xce\xd8\xe1\xa7\xe9%0\x93\xcc\x06\x1b\xf5ZP" + - "\xdc\x0a\x0a\xbd\xe4\xa7\xe9\xa50Hf\xc3\x84q\x03(" + - "n\x07E\xc6\xf6\xd3t/X\x9c\xb3\xe1\xcd\xde\x0a\x8a" + - "{@\xb1\xdc\xf2\xd3\xf4\x1b`qb'\xde\x05\x8a\x07" + - "@qb\xd1O\xd3}\xb0\x7f\x9c\x0d/p?(\x0e" + - "\x80\"g\xfaiz\x19\x0c\xab\xd9h\xf9\x80\xe2)P" + - "tl\xf7\xd3\xf4r\x18V\xb3a\xa5}\x0a\x14/\x81" + - "\xe2\xa8m~\x9a~\x13\x86\xd5lX\x0b^\x02\xc5\x9b" + - "\xa0Xe\xf8iz\x05\xcc=\xb3a\x1a{\x0d\x14\xef" + - "\xce\x8eP\xdf\xb4\x0b5\xd04\x0d\x01\x85\xc0K#\xb6" + - "\xfe\xa0\xfdw?jH\xfc6\xd8\xad[\xba\xe3\xd8;" + - "\x07m\xaa\xe7\xbb\xb0L\x9e\xf3<\xd3\x84\xbfl\xdaw" + - "/\xfbCO\xe4\x8d\xa0e\xa1\xe4\x9e\xb2\xbe\xa7\xa3\x9b" + - "Jr;\x9a\xf0\xf7\xac\xbb/5~\xd8\xa2kB\x8a" + - "R,c\xec\x19\xa3\x0c\x8b\xf0\x07{2\x98\x9aO\x13" + - "\xfeu\x8bz\x9e2\xae\xba\xf3\xfa \xff>\xa7\x87\xb9" + - "\x92\x89\x177\xef\xea\xbb\xfc\xaa\xf3\xbf&<\xb5y\xe1" + - "\x83\xe4\x8e\x88\x84\xff\xbb\xbd7,\xfe\xde\xdd\xcf\xdc\x10" + - "\xe2\x16\x08Xh\x12\xde\xec;\xffD\x8f{\xc4\xf0\xbf" + - "\x19\x96H\x18c\xacg\x8cY\xd4\x13\xe5\x011\xb8\x89" + - "\xd05|x\xdb\xd6\x197\xdf\xf7\xcf\xfb\x84k8\x83" + - "U\x114\xe1\xdf\xbc\xf0\xf7\xfe\x92_\xdcrOX\xa8" + - "\xc0\x10\x92\xd1\xa5\x0a\xc0\x00M\xf8g~\xf5\x8d\xa1;" + - "o{\xf1\xeb\xb5\x1e\xda\x85\xa6\x82\xcfQ^P}\xf8" + - "\x99\x01e/\x878U\xa2Wpg\x9b_)\x1f\xfd" + - "\xbf\xf2\xff\x18\x9c:\xc0BE:\xfe\x84\xff\xa5'>" + - "\xfa\xc5\x05\xd99W\xa9\xcf\xb9\xb1\xb7\xbb\x87V\xd4@" + - "\xbc\xf5\xe1w/\xff\xe0\xc4s\x1f\xa8\xf1\x92\xb9\xbb;" + - "\xd6[\xcb\xcf\x8cg\x1br\xf4\x1c\xdd\xee\xaaw\x15>" + - "\xc5\x96\x8e\xcd\xad\x893\xec;\xc4S\xecv\x99\x95?" + - "\xc8k\x84\xf1\xc8\\WG\x08\xf4\xa0\x88\xdc\x141d" + - "*\xc2\x0ep\xbf\xfb/\xf9\xca\xfar\xe9\xc5\xcb\xc3z" + - "\x9d\x12\x03\xa5E\x0bH'V\xec\xd3\xec\x02M\xf8\xf7" + - "_\xf3\xfd{\xd64M\x7fM\x19\x91\x08I\x12\x14\x05" + - "\xcd|\xfa\xb6\xcdk\x07\xd7\xbc.\xc9t\x83\xaaY\xb8" + - "\xc8\x09\x97\x0c\xbe\xd4\xf8\xa7\x1b\xaeQ\xb4\x08/N4" + - "\x1b^\xfd\xf7\xd2\xf7\\\x15]\xb4\xe7\x8fa_\x88," + - "|\x1a\xb0\xcfp\xc8\x8e\xaf5\xdf\xf7\x85/N\x7fI" + - "\xed1\xb8\x07\x1aT\xa2\x04o>\xe1/<\xe7\xcb7" + - "\xfe\xdb_}\xeb\xde\xa0i\x00\x14C\xe1c\xac9H" + - "6\x9f\xf6\xd3e_\xbc\xe6\xaa\x9b\x83Ab\xe9c\x1b" + - "Ky\xac*P\x06q\xc2\xff\xf1\xb6\x01\xc6\xfe\xe5\x8a" + - "_J\x18\x0f\xd3D\x84\x0fu\x94\x86g\xfd\xc9\xce\x87" + - "\xce\x19\xd9\xf4\xc7\x9f\x06g\xddi\x8c\x18Yxk5" + - "[O\xbf\xef\xdcO\xcf\xdd\xf2\xe2Sa-\x0f\xf7\x0a" + - "\x9fD-\xd7\xad\xfc\x9e\xef?\xff\xe1\xf6'\x96\xbe\xf8" + - "bp\x17;D~,\xef\xed\x07\x07\xbe\x1b;\xb9\xb0" + - "\xef?dG\xe5u\xa7\xdf\x9b\xf4%}\xfd\x9aSN" + - "\x1f\xfd\xc5\xaf\x03\xdfr\x893\x16\xd2\x84_\x9f\x1em" + - "\xff\xdb\x95\xe7\x7f/8AYT\x0c\x13\xea\xd2\x84\x7f" + - "\xfa\x9f~\xf2\x9b]/\xbcp~P\xe5\x83Y\x0c\xa0" + - "\x98\xb3\xe6\xf9\xbf\xbd\xea\xae/=\xaa\xbe\xa0\xf5\xa5\\" + - "\xd5\xacum\xdb\x97nj\xfb\xf5\x8d{+_\xa3U" + - "\x88\x04tCpH\xc5\xd3\xfej\xcbW7t\xedz" + - "Y\x997\xc70\xf3\x81\xba\x95\xeffF\xf3\xc2\xc6\xe6" + - "#\xf7\xdc_q\xdb\x83\xfaN\xe8\x95 d\x13\xa0\xe5" + - "F\x98\xd3o\x1bb\xca\x90}\xf2_\x1f\xbc\x7f\xe5\xe5" + - "\x8f\x0c\xfd\x932\xcc\xc3\xe6a\xb4;\xfc\xd6\xb7\xbf\xf0" + - "\xe0\xe3\x97\x1cv\xdb{aez\xa9d\xea\x961N" + - "\x07\xf5\x9d\xea#\x04\x17\xf7\x1c}d\xc4\xc8\xf5D\xc6" + - "\x98r\xe5\x8a2\xb4\xcf|\xe67\xfb\xae\xf5\xfetk" + - "X\xb1&\x06y\x84W\x8c\x15\x0d\xabP9iU\x0f" + - "u\xdb\x19vM\xbd\xd8\x15\xe1\xe4\x9c\xb2HKt\xd2" + - "-/\xaf\xf8\xd6\xf3\xcb>\xba\xb0\xfa+\xd2\xa0iH" + - "\xb1\xaa\xde[\xcdkl\x18v\x99\x13\x19\xd3'U\x81" + - "\x85O\xf2o\x1fo\xeb:\xa5\xd8\x16\xe2\xe6\x043\x06" + - "5l\xabg\xdccN\xcc\xd2\xcd\x1a3\x87)\x90\x8e" + - "\xaaFk\xf5=\x94\x8dS\xf41\xa3\xc0;\x06k\xb1" + - "*\x9f\xf3\xf3/\xdc\xf6\x05\xb3\xf3\xc0%5\x9f\x93\xa3" + - "(u\x87\xf5)\x07\x9f=<\xe6z\xeb\xec\x09\x97\xc4" + - "=#\xb7\x1d\x06d\xcbg\xff\x9e\xd1\xa3^Q\xfb#" + - "o\x17\x19\xf5\x9c\x89\xca\xa1;\xf6\xc5\xcc[\x9b\x1bJ" + - "\xff\xae\xb4\\\x03\xeb\x1auX\xd5'\xfd\xfb\xcd\xf4\xc2" + - "u\xb3\xcex\xbcz,E\x02\xe4\xa7\x83w\x87\xed\x0c" + - "\x9f\xcc&\xd68T/\xb2\xca\x13\x1f\xf5\xe5_\xf5h" + - "'|\xfa\x80\xec\xb8>}\xc2.{\x11\x85\xb6%x" + - "\xd1\xd7\xbe\xb0\xe8\xb6\x86\x9f<\xbf\xa7\xfav#\x0es" + - "\xb3\xe5bQ\x17\xcf\x17\x8c\xbe\x7f\xdd\xf0'\xed\xb4\x19" + - "?\x7fZ4\xcf\x8b\"\x19\x1a\x9c8\xb8\x89\x8f\xa7\xbd" + - "\xf5\x8dG\xcc\x13\xee\x111\xd5a\xdb\xf6h\xc2\xef=" + - "\xfa\xcc\xbd\xa5\xaf\x1e{\x9d\xfa\x8a\xfauG'\xedE" + - "\xe61\x07\xa6\x94\xecgw]\xfe\xe3\x8b\xeb\x9e\xad\x98" + - "R\xf4R7\x15\xf3\xb8|\xcc\xef$\xff\xf8\x8d\xaf\x7f" + - "\xe6\x0b\xfb\xe4\x12\x03\x16\xd5\x86\xc2\xcfU5\x0d\xac\x9aX\xf9\xc6" + - "?\x7f\xeaW\xe1\x8c\xa6\xd2\xf7$\xfc\x9f\xffqZs" + - "\xfe'_\xfaA@\xb8\x1cBh\xd5\xf1\xda2Qe" + - "8\xb5\xfd\xf2\xf3U\xdf\xeb\xfb\xafSgI\x00*\xdd" + - "\x81^*\xf2\xd9\xf8\xb9\x9bo\xb9\xe4\xa8\xcf\x19\x17\xc9" + - "\xe7\x1e6\xac.\xbdH\x99\xa3K\xdc\x8aj\x832\xc0" + - "\xf9\xd6jp\xf8\x04\x83\xe1\xbc\xeb\x0f[\xd7\xf8\xdc\x09" + - "\xf7T\x7fA\x11\xe5\x0b\xaa\x98\x8a\x16=\xf8\xdb\xc3W" + - "\x97\x1e\xf9\x9db\x9ay\x86\xc5L\xbe*\xad\xb4\xde\xeb" + - "\xfe\xd9\xb9\xda\xef\x03\xedN#\xcf\x06m=O\xb9\xed" + - "\xcbS &\xdf\xean\x0e\xf4\xd7F\x13\xfe\xeb\xfft" + - "\\\xd3\xf6\xf6\x1d\x0fW\xa4\xa7;%" + - "\xc3\xb4\xa9\xd7\xa5\x8b\xf4,\x9a\xf0\x1f\xb2\xfeu\xfa\xa6" + - "\x87\xb7\xfe\xd7\x14gZ\x06gZ\xd1\xd7\xfd\x95+N" + - "\xbd\xfc\xb9)\xda,\x876\xc9\xed\x9b\x7fey\xdf=" + - "{\x8a6+\xa0\xcd\xc6\x1b\x06\x9e]2\xf6\xf8\x8dS" + - "\xb49\x0e\xda\xfcC\xb4\xf4\xd1\xe7\xcf\xbb\xf8\x83)\xda" + - "|\x0e\xda\x1c\xa0}G\x189\xeb\x9e)\xda\xac\x846" + - "s\xaf\xb9\xa6\xb7\xf1\xcdY\xefN\xd1\xe6xhs\xcc" + - "/3Zwl\xb4\xc2Vp=\x87E\xf4\xa2\xf8\xd8" + - "\xc5\xb7\x9e\x99j)P\x8e8UL8\x87\xdc\x90\x8b" + - "\xf6]b\x12\xe3\xcb\x0c\xbe\xf9\x83\xb4\xae\xbc\x9f\xf6\xfc" + - "T\xb3\xd4\x947\x14?\xf4\x01\xca\x1da\xe6L\x8d\xd6" + - "\xc1\xf7\x1f\x09\xbe\x7f\xe7\x10_hU\xb7\x0f\xea\xed;" + - "\xe1F\x96\x86\xdb\x97)\x1a\xb4\x1e\xaaA\x9bl\xa0;" + - "\x1b\xca^\xa9L(\xd8\x7f\xe7\xff\xa8e\x80\xfdb\xf6" + - "3\xea\xf4jX\x85\xf54\xc8\x0d\xc2\x9e\x1e\xfb\xc7o" + - "\\y\xce}\x1f\xbcVa%\xda\xae\xf0,\xac\xbf\xab" + - "\xde\xb9\xfb\xfa\xbe\x87\xa4\xcd\xc1)QI;\x0b\xfcS" + - "\x9f\xbf\xe9\xdd\xb5\xcf/=\xea\xeejO\x0b\xd1p\xd7" + - "\xfa\xe3[\xde\x9e\x7f\xda/.\xdcS9\xc9w\xb8\xd4" + - "\x95\xc0}\x09\x7f\xffO\x1f\xbc\xd9\xfd\xf6\xc8\xb7\xc2\xe9" + - "\xccd\x8e\xd7\xcd\x86\x89\x86\xb3\xd4\xa6\xaf\x16\x0e\xbb\xef" + - "\x0f\xe7\x87;\xc1\xc0\xaa#\xf1\x83\xb2\xbce<\xbb\x9c" + - "\x1b\x95\xea\x1f\xbc\xf1\xa7\xeeE\x8f_\xf6\xb5\xd0\xd4\xab" + - "\x9a+\x96r{s\xf3\xa9%\xf3\xe9o\xffx\xaa\x19" + - "\xa5\x15[\x9d\xa7-\x7f\x89\x9dp\xd4CS\xb5j\xc3" + - "V\xcdw\xd1B\xe1\xc0\xe3WO\xd5j\x19\xb6z\xe2" + - "\xdck\x0b\x7f~\xee\xf2\xc7\xa7j\xb5\x1c[\xb5\xbf\xf8" + - "\xc6Y\xeb\x17\x9cz\xfbT\xadV`\xab\xd1\xfd\xdf\xd8" + - "\x97\xfd|\xf7\xfdS\xb5:\x0e[%\x7f\xb0s\xcf[" + - "\x1d\xc3\x1f*\xb3u\x1ev\x8d\xd4\xca\xb3\xfc\x86\xb2\x87" + - "\x0e!m\xd9\x89\xef\x0f\xd7\xffC\xe0\x88\x806\xbd\x16" + - "\xec\xa5\xbe\xff\x85'W\xae\xdev 4!\xf5\x12\x1c" + - "C\x13\xfe\xb9\xef\xbd\xf7\xe9e\xbf{\xe7\x06u,\x04" + - "\xe4\xcf\x09\xff\xa9\xf7\xd7?|\xe4/_\xbcB:\x00" + - "wv\x94\xf3\x86M\x82/\xf2\xd5\xdb\xee\xf9\xdc/w" + - "\xfc&<|\xd8\xb6\xb7\xc3BO\xda;\xcb\x9e\x87\x8e" + - "\xb0\xea\x05_\x87\x13\xaca,\x92\x1f\xd6s\xdb+M" + - "\xc7\xc5\x9f\xfb\x97\xf2\x03\xbf>\xe9\xad\xaa\x0d\xc9z*" + - "\x80 \xfbc\xa6\x0e\xe7\\zli\xdfC\xef4\xbf" + - "Um\xbd\x87,=\xa1/\xf6\x98\xbaw\xce:\xab\xff" + - "\xc5k\xc3\xce\x1de\xaeg\x95=\xe9\xad\xbd\xe5\x87\xd7" + - "\xdc1?\xfe\xef_\xaf\xc6\xa1\x8d}\x82\x8c\xe5M\x86" + - "k\xd8V\xbfm\x1a\xb9\x09\x01\xd0j\xbb\xbc\xe6B\xc9" + - "\xddm\xab\x95\xbb{\xa4\xcc\xdd\x0d\x00\x88\xaf\xdbB\xc8" + - "\xc0\xb5\x1a\x1d\xb8U\xc9\xe0\xbey\x9d\x9a\xbb{\xa2\xc8" + - "\xdd\xdd\"\xd3t\xc3\xdc\xdd{\x87% ]\xa6dx" + - "\xb9\x10\xe4<6!\xb9\x98|\xd4t!N\xf80\x18" + - "l\xaf\x0f\xccxh\xdb\xe9\xe1,9\xa1\xef\xc4\x9bTk\xd52\x19\x09N\x1203V\x94x\x1d" + - "\x92\xd7'H\xf7\xd3X~`\xa1\x16\xa5\x14\xb3\xe3\x1a" + - "1\x85\x16\xb3\x0f\x8f\x12\xd8\xab >\x023Y%\x8c" + - "\x8c\x16\xe5\xa9q\x8b0cU\xc2\xc5\xc4D\x15z+" + - "f\xb8\x86@\x8d\x09\x81\xf3p<\x9e]\xf2\xf7D5" + - "\x9e\xcc\xd6\x81\xcdeBo\x9d\xc0y\xe8\xc5\xc4\xda\x90" + - "3\x08\x8b\xd9\xa7\x11\x92Z\x8f\x89\xaf}a\xe2nC" + - "4H\xdc\xbd\xb0\"\x11\xb71\xca\x13\xd9\x94D\xdc\x8b" + - "\xe8!\xb0IB\x84\xf7XE\xc2z\x0d\xc4\x92Z," + - "f#\xdedJ28\xb8k\"g\xe2\x12\x11d\xca" + - "\xe6t\x13\xa1\xb0\xc2\x93\x1d\x8c\x8e,t_S~\xf6" + - "\",\x02\x15\x14i=\x8eCb\x0aNt\xdc_\xfd" + - "\xd0\x86\xff\xf8\xe1\x98\xf3bu\xca{\x15\x0c\xa4\xf0\x82" + - "\x85%\\\xb82c=\x08\xff\x90\x16\xe2\xb7\xb1\x83\xd7" + - "Y\x18\x9c\xde\\\xe7\xf4\xe6\x9b9\xa6\xf1F\x0e\x97\xbe" + - "~\x1db\x1a\xf7\xb6!\xa6q\x07\x1c\xd0\x80\xd0\xc6\xb4" + - "1\xb9\xa2\x93\x90\xdd\xc2}\x1c36dc9\xddA" + - "\x9c\xae\xfc\x84\x05\xbd\xd2>R\x86/\xd9g\xe3\x1es" + - ",L\x04\xce\xa0\xb7t\xb7\xe7\x18\xc5a\x93\xa1G9" + - "o\xe8\x05\x82\x15\x1eF\xcev\xd8\x14I\xfc\xa6]\xd8" + - "\xc4\x1c8\x1d\xe9\xa7\x14\xfa;\x19=84\x0e\xdf\xf8" + - "\xc0\xbe\x07\xbb \xc0F\xadQ\x02\xd1&2\xddOT" + - "\xa6\x92\xd50\x95\xac\xe4\x8cC\x9f\x14\xb7|*\xc6\x0c" + - "\x95\xe4\x9e\xf3v\xc5M\xc3\x9bP\xea]\xb6\xe0{\x98" + - "\xcbad[:\x09\xf1\xf5B\xc1a\xaek\x10m\x8c" + - "\x81\xa1n\xe5u'\x0f\xdd\xe40S\x1fWj@\xa6" + - "Nx\x16 \x831}\xd32\xb8\xd4A\xd0\xa3h\x80" + - "\x1e\xb5N\xfd\xec\x03\x84\xe6V\xda\x1c\x80D\xad\xa5\x0a" + - "\x86E\x0f\xcaO\x0c\xf3\xef\x03\x0c\x8b\xcdx\xfa\xa10" + - "\x9f>` *b\xfb\xd1\x10\xe9\xb9>\xca\x93d\xcf" + - "\xc1\xf6\xbbBD\xe7X\x1d\x9fV.\xc3\xf62o\xbe" + - "\xa1\x9eO+7c\xfb\x1b*\xa8\xce\x1b\x91\xea\x1c\xda" + - "\xdf#\x11\x9a\x1b\x02\x84fh\xffX\x00\x15\x13/\xa9" + - "\x19\xd4\xf0\x83\x7fy\xe1\xd7>\x09\x84r\x12\x90e-" + - "T\xcaI\xe0\x96\xb5`*\xe9Xu\xa3\xb1\x1a\x8d\xf4" + - "\xeaF\xfaA\xc0-\xebjC\x98( \xb0\xa2\x0cL" + - "aI\xe0\x15\x94=\x9d\x15,\x09\xfc\xb3o]\x87\x9f" + - "\xfd1\xfc\xb3_\xb4\x98\x90X\xa1\xe4\xee\x16e\xe8\xed" + - "\xc3\xcc\xc8\xdbe_Tc-#X\x17\x88\xff/W" + - "\xfe_A\x08\x89\xbb\xc3\xba{\xc8R\x90\xde\xa2^\xc0" + - "}\x83f;J\x89'\x9f\x97\x8eX\x8578\x97\x17" + - "\x98&;e\x19X\xbb\xee,m[\xd6\xba\xdb\x1e_" + - "\xba,\xd7\xbat\xb7\xed.]\x9ek]zH(Z" + - "I\xca\x85\xddqk\xf8I\xdc\x18\x851rm\x14\xc6" + - "ZT\xf9$nF\xf9\x0d \xbf=\xaa *\xdd\x16" + - "m#${\x13\xc8\xef\x8a*\x88JwD\x8f$$" + - "{+\xc8\xef\x89*H\xaaw\xe3yn\x07\xf9\xfe\xa8" + - "\x02\xa5zot\x15!\xd9\xbb@\xfe@T\xc1u\xb9" + - "\x1f\xe5\xf7\x80\xfc\xe1\xa8X\x81\xe1\x9bx\x10\xcf\xbf\x1f" + - "\xe4\x07\xa2\xa2\xf6\x04q]P\xfe\x00\xc8\x1f\x8b\x8a%" + - "\x12Q\xcbQ\xfe0\xc8\x9f\x88*\xa8\xe5\x8f\xe3\xfd\x1c" + - "\x00\xf9S \x9f.\xc8l\x9e\xc4\xf6\x8f\x81\xfc\x19\x90" + - "\xcf\x88\xf1\xa5\xf6i\xbc\x9f'@\xfe<\xc8\x9b\x1ax" + - "\xca\xf8\xb3Qd\x86\x02\xf9K \x9f)\x98\xc5_\xc0" + - "\xf3<\x03\xf2W\xa2\x0a+\xd7\xcb(\x7f\x1e\xe4\xafE" + - "\x05Ux\x82\x90\xd4\xab(\x7f\x09\xe4o\x82<9\x83" + - "\xa7\x8b\xbf\x1e\x85o\xfa\x15\x90\xbf\x0d\xf2\xe6&\x9e-" + - "\xfe\x16\xb6\x7f\x0d\xe4\xef\x82<5S0\x12\xa3\xfcM" + - "\x90\xbf\x0f\xf2t\\\x10\x12\xe3\xfd\xbf\x0d\xf2\x0f\xa3\x02" + - "\x0f\xb3\x85\x90\xd4\x07\xd8\xfe\xdd\xa8F\x07\x91i9\xc9" + - "\x13\xc5?\xc2\xc7z\x1f\x9aGA>\xbb\x99\xe7\x89\xd3" + - ":h\xfe!\xc8\x1b@>'\xc5\xd3\xc4\xeb\xea\xda\x08" + - "\x19\xac\xd3hv\x06\x129\xa7y\x92x#\x1207" + - "\x80<\x0d\xf2y-\x8f\xe7\x857" + - "\xe1\x8d\xc8\x0bf>\xc5\xd3\xc2[\xf0y\xc2\x0b&\x17" + - "\xcc\xe7Y\xe1s\xf1\x06\xd3 _\x00\xf2#\x0e\xe3I" + - "\xe1\x87\xd5\x81%\xb6\x00\xe4K@~\xe4\xe1<'|" + - "\x11\xc2\x04-\x04\xf9r\x90\x7f:\xc3S\xc2[\xf1\xfc" + - "K@\xbe\xb2.B\x8f8\xaa\x81g\x84\xaf@8\xa3" + - "\xe5 ?\x11\x1e\xf4h\x9e\x0f\xbe\x1a\xd1\x95N\x00\xf1" + - "ip\x9a\xcfP\x9e\x0e\xbe\x11o\x7f\x08\xe4%\x90\x7f" + - "\xb6\x83g\x83\x17Qn\x82|\x1c\xe4\x0b\xcf\xe1\xc9\xe0" + - "e\xec\xc7\x12\xc8w\x81|\xd1y<\x17|\x02\xe5\x1e" + - "\xc8\xcf\xae;\x18/Y\xa6h[\xdeh\xf0+\x96\x97" + - "x \x7f\x01;YL\x1fY\x1a@F\xc7\xf4\x91V" + - "\xe5\xff\xb6\x90k\xcc\xb0\xf3,T\xe4\x1c7\xa4\xfcB" + - "\x1a0I\xf9U\x94\xa7\xca\x95s\xe1\xff,\x97S\xe4" + - "\xe1\xd1T\x0f\xa5\x9e\xad\x9c\xdf\x08[\xb7\xdbEV\xd0" + - "\x95\x93\x1a\xe1\xc1\x9a\xa1\x88\x9d\xf0\x88\x0c\x1e\x11b`" + - "\xe3\xafn\xdb\x83\x853|\x98n\xdb\x0bA\xb3sv" + - "\x9e\xb9}m\x0a\xaf\x99B~f\x86\xf2\x8c;\xd6!" + - "\x1f\xa2\x02\x8a;|\x84B^\xed/\xd9\xd8st\xcb" + - "-\x1a.uy\xd8\x9a\xc9\x83\xfc\x11\xc3\xc3\xdap\x12" + - "\x1b\xd3M\xa57r\x15(\xde\xb5\x91\xb7\xff{\xf8\xde" + - "\x9e\xbd\x13a\x19\x14\x88\xdc\xdd\x9e\xcdT\x98\x94\xdd\x9e" + - "\x9d\xab\x80M\x99\xc2b\x9cd\xberd\xd0\xdfm\xf8" + - "\xa7?n<\xe6\x07O\x93$\x1d\xae\x02\xfb\xef\x0f\x97" + - "\xb2#\x90\xffk~D\xa3\xd9\x85\x11e);\x1a\xe1" + - "\x98\x8f\x02\xf9\xd2\x88\xb2\x94\x1d\x83\xfceK@\xbe2" + - "\xa2,e+\"\x98\xa0\x0c\xf2\xee\x88\xb2\x94u |" + - "3\xf2\xb8\xf5E\x94\xa5\xac\x17\xf9\xce\xd6\x82|\x08y" + - "\xc4(_\xca\x06\x10\x1e\xba?\xe0}\xa3)J\xfd\x85" + - "[_\x7f\xf2\xe1\xff\xfb\xed\xff\"\xa9\xcd\x11\x98\xd6b" + - "1\xbe\x8c\xf5 \xf2t7\xb4\xedG.\xb8\x08_\xc6" + - "\xd6\xa3\xbc\x0f\xe4\xa7!\xf4\xb40\xed6F\xae\"$" + - "{\x1a\xc8\xf3\x08=-\xc87t\xbc\xf7|\xc8)7" + - "}\x1a_\xc6\x8a\xd8\xbe\x04\xf2]\x11\x01[\x06\xcb\xd8" + - "\x04\"a\x8f\x83\xfc<\x84\xa4\x9e\xc1\x97\xb1s\"h" + - "\x9a\x86\\s3)_\xae\xceG\x8e\xb8= \xdf\x87" + - "\x9clZ\x1a::u)\xca\xf7\x85\\s\x89h\x9a" + - "6S\x9a\xba&\xf2\x10\x98\x17 \xbf\x159\xe5\xea\xd2" + - "\xd0\x0f\xa9\x9b\xb1/%bws}\x1a\xdeV\xea\x8e" + - "\xc8-*\xa7\\\x15!Ra\xc2\xb1\x11K\x88T\xf1" + - "M\xd7b0\x0b\x14\xd4e^\xc7\x18s\xf4L\x81\xa9" + - "z\xd73FF\x90\xc2z\x8d\x9e\xf3l\xa7\x8a\x04u" + - "\x10>X\xc3>\x04\xc3Y%\xac \xe7>\xc8\x92x" + - "\x891\xc9j^\x9b\xf1\xac\xe2\xfe\xd6\xe8\xae\x87\xf8\x8b" + - "\x07\xbb\xf9\xac\xa2\xaf\xbe\xf9\x8a\x83\xc3\xfb\xcf\x18\xb6r" + - "P\xdc\xb1M\x95\xb2\xb7\x16\x01C\xf8\xa1I2\x88\xf0" + - ">\x04_\xb4\x8c\xad\x07\xcaHp\x93\x05&\xe7\x93:" + - "\xc9\x187\x88Y)\x93U\x95\x8f\xb0)^\x19\xb9?" + - "X\xad\x7f\x05P\xa83\x99\x0dk\x86\x16\xc5*\xeai" + - "\x84${\xb6\xa9\xacb\xdc\xb3\x824F\xc8*6\x1a" + - "\xa1\x09NP\x93d\xd00\xaf\xd1\x81\xb3#\xd4\xb7s" + - "9\xb3\x9cg\xf9*@J\x87\xe9\xf9\x09\x81\x12Y\xb5" + - "/\xb1lo\x10\xb4\xe2\x88O\x04\xbc\xd8'\x9c\xed\xe1" + - "&=D\x0a\x189\xf7\xb1\x1f]\xff\xc5\xfasp\xc6" + - "\xc3l\xa01\x91\x0d\xa8\xc2\xdb\xb6)`\x92\xc1\x06\xbe" + - "\x0c\x1b\xf8\x12\x87s\x08|\x81\x17\xb4\xa9h\x0e\x82F" + - "\xf8\xe2m\x92\xfd\xeb\xbf\xc9Pf\x077\xc6+fC" + - "G{x\xf7\x07u\xd6dE0A\x94\xe4o(1" + - "\xabd\x98\xb6\x97\xf5t\xad\x82lf\x1d\xee\x8aZ9" + - "\xec\xce1|Wt\xb4\x83\xdb\xb6#\xb6\x10\xe2\xe79" + - "2q\x1evb!&\xb1\xc6\xf2\x01y\xbe\x846\xce" + - "\x0c\x9b\x86U\x08\x10\x87\x0d\xa2M\x89\xc3\x93\x15\x81P" + - "\xd7-k\x0eG\xe1\x91\xfd\xeeH\xae\xe5\x80l i" + - "" + - "\xfc\xc3\x99\xbf'\xc92L\xf5\x01|\x82~\xa7\x18f" + - "\xa5\xc8\xe4pk\xf8\x09\x0by\x04\xc5\xa7\"\xba\x01\xcb" + - "w\x0f\x93\xda\x80\xa6As\x1a4\xcf`\xfbCP7" + - "\xd7\xa0\x15\xccz\x0e\xb3\x0a`\x85(\xdd\xcf7\xa5\xc7" + - "pP\x92\xa3\xd7q\xae\x9f\xc5\x9c\xeb\xa7M\x81()" + - "\xd9\xb6\x83(\xec\x0e\xcfL\x8d\x17l;\x9f)8L" + - "\xf7\xa6\xe8\xe4\x8d\"\xf1C\xbeq\x85\xd8\xe3*\x85\x11" + - "%\x18\xdc\x0f^/\x88=\x9eP@*\x1e\x87\x81\xfc" + - "\x98F\x07\x9eQ\x88=\x9e\x86w\xf4T\xc0\x93\x12\xad" + - "\xe2IyM\xae\xdf\xc9Wa.xE\xa3\x03oG" + - "(\xe5\x8c\x1e\xc9\xb7\xb6I\xe2 \x05\x02{\xa0\xcc\xca" + - ",khgJD\xaa*e\x97]\x01A\xe5\xe8;" + - "QL\xe2YC9(\x14g*\xc1\x07M\xdd\xf5\xaa" + - "\x9c2(\xcb\x96\x18#4_![c\x98\x8cT\x80" + - "QLQ6>\x90\xb33\xe8\x1bA\xce\x8f\xff\xfb\x8f" + - "\xb7\xfd\xe9\x07\xcd\xf3\xfe\x9d$[\xf7\xfa\xaf\x7f\xc5l" + - "\xba\xea\xdc\xc3_#\xc9\x15W\xf9\x9f\x7f\xedG\x9f\x9a" + - "I\xe9\xab$y\xfc^\x7f\xefW\xffv\xfb3\xff~" + - "\xf6{$\xb9z\xaf?}\xc3\xd7_X\xf77\x97\xff" + - "\x88$;\x86\xfd\xad\xff\xf6\x7fz\xf6\xfd0{6I" + - "v\\\xef\x97\xda\x0a\xf3\xce9\xfb\xcfw\x90d\xcf\x99" + - "~\xe0z\xa1\x81\xef\x852?\xbb\x89O^T\x00\xb1" + - "\xc0{\xael\xc8SM+d\x02\x81\xd6\x0f\xe0hI" + - "\xccv<\xbf\xdb\xe1m(:w\x06YIH\xb3c" + - "\xfd\xb69A\xda9e\xe7\x14\xa1\x92&*\xea\xe2\x93" + - "\xd7\xec\x95q\x91\xa6\x88(\x8aO\xde<,\x03#M" + - "\x9a\xa8\x88O\xdeq\xbd\xa4\xeai\x8a\x8ar\xf8\xe4\xfd" + - "\xeb$-OX\x0b\x9f|d\x15!\x03\x0fp\"\x9a" + - "\x8ci\x17\x86$\xe6uq\xf2\xb3\xd1\x84\xec\xe2 \x1a" + - "\xa2>-M\xc8^\x0f\xc3R5\x9e\x9f&\xe4\x0b\x09" + - "\xdb\x89\x1e\xc1\x15=|C\"\x8a\xe7\xe8;\xfb\xec\x82" + - "\x0c\x19\xd7\x06!\x93\x9e\xdb\x0cf\x88\xe3\x9a\xb4\xe0\xd2" + - "\xd8c\xd9\x7fl\xbd\x93$\xe9}~_u\x12\xb9@" + - "+\x1cX\xa9Ei\x13\xa5\xfe\x11\x9f\xdd\xfd\xcc\x96\xd6" + - "\x8e\xff$\xa9\x09\x04\xb0\xa6\xc2\x93S\x8dF\x12\x11\x9e" + - "\x1c\x036\xda\x12\x8d$!\x00z\x8b\x88\xa5\x1d\"\xe0" + - "\xa3\x136\x8e\x90\xdf\xf7U\xd0\xe75\x08\x07\xc99x" + - "zt\xaa\xeeA\xe7l\x00\x04\x8bx\x13\xe7\x81\xfc\x92" + - "\xc09\xbb\x80\x90\xd4\xc5\xc8\x1c\xb0G\xd2\xe7E\xb9'" + - "\xe0:\x94_\x1d\xd2\xe4\xc5\xea\xb8'\xa0\x9a&oF" + - "\x8a{\x02\x1eE\xdc\x0at\xb6>\x83\xce\xd9\x19|\xc7" + - "\xff4\xc6\x88\x9e\x02\xf9K\xe8\x9cm\xe2[\xfe\x17\xf0" + - "\xb9\x14\x1c\xef\x99|\xcb\xff*\xb6\x978\xde\x15\xfc\x14" + - "\xa3\xba\xdb\xc7\xf4p\xfd\x8d\x8d\xe4v\x86k1&\xf2" + - "\xad\xb7-\x92\xc1\x88J8\xf8\xcc)^\x14\x8d\xcb\x17" + - "*\x10\x9a\xf4!\xdd)(Q\"\x81=dP\xab\xd0" + - "\xcdL]\x82\xf6\xb5c\xbaQ5\xbat;R\xd5U" + - "K3\xdb\x98\xb3}\x12\x10\xb5k\x9bc\xcc\xe9\x19\xa7" + - "L\xb0u`aO\xb8\xfc\x8d\xdae3\x9f\xf5\x88f" + - "\x97\xa4\xc1l\x9a\xf6\xce\xa1Q\x87dl\xcfS\x18\x0a" + - "P\xde\xe9\xe8D\xdb\xce&1\x07\xd4\xff\xa5qW\x0e" + - "\xc6\xd4@\xa9_~\x819?~\xf7\x1f>&\xc9\xc6" + - "s\xfd\x13\xdf\xfc\xccW/z\x7f\xf5\xcfI\xb2q\xb1" + - "\xdfm\xb8\x9e\xa3\xe7<\xca\xf2C\x13%\xe6\x12\xe4%" + - "R\xb1U.T\x16\x9f`\xedz\xc1Q\x16\x9fH\x03" + - "\x9fw^\xdd\xa6,>b\xe9z\xeb\\\x85\xb5.\xda" + - "\xc8'\x9d\xf7\xb6)l^\x02\x98>\xf9\xd1bB\x06" + - "\xde\xd7h6\xaa\xc2\xd2S\xfa\xb3\x0a\xc8\x95\x00\x96>" + - "I\x1118\x08\x86\xfa\xfaN\xddah\x81s|+" + - "\x0f\x16x\x11\xbf\x0bt$\xe3f=&!\x8e\x0c\x97" + - "?<\x89\xe7<%h\x9b\xaf\xee\x11\x9a\x90\xfd\x17T" + - "\x1c\xe99\xd6\xcd\xe3\xb1e\xdf\xbb/X*\"\xd7" + - "\xf2\xb9\xbf:\xfe\xadM\xe7\xce\xf1\x1d87\xcb5!" + - "\x9a\xe0s\x7f\x19\xe7x\x0f\xe4g\xe3g\x92\xe4\xce\xf1" + - "\xb3pn\x96\x94\xaa4\xca\x9d\xe3\x17`\x1c]\xce\xfd" + - "0\xc7\xcf\xc3\xb9\x7fq\xc5\xdc\xdfP\xcf\xdd\xd4w\xe3" + - "\xdc|\x17\xc8\x9f\x08\x02p\xf3\x09I=\x8e\x80Va" + - "\xa0-Y\xff\x1d\xbe\xe6\xbc\x8aq\xfdp.ON\x9b" + - "\xc9\xbd\xd5o\xe1\xfd\xbc\x1dP\xa1&\x1a\xb8\xb3\xfa\x03" + - "\\\x12\xde\x07q4\"p\xb1`\x89\xa2\x91-\x84\x0c" + - "F4\x9a\x9d\x81\xbe\x9b\x06\xbeB5\xa2\x7f\xa9\x01\xe4" + - "\xe9H5\xfdF\xb1\x94C\x16!j\xd8\x96\xb2qG" + - "\xc4k\x0e\x86D\xe3\xfeH\xba\xf3\xbe\xe5\xeb\x0a\xdf\xad" + - "\x01O\xf4?\x860\xca#!\x82\x8di\x1c\xd5\xb3\x7f" + - "\xbc\xe4\x1a\x93\xa9\x09\x02~w\x8dM\xadkG*\xf7" + - "I\xfa\xb2\x8b\xe0\xa7}$n\xc0|&\x19m\x0e\xb6" + - "\xc8L\xb5`\xf2\xa3\xbal\xa2\xb9\x0a\x0b\xab:pi" + - "B\x8e\xea\x83\xe6\xf9Lb\xa5\x0c+\x80\x14)\xff\xf8" + - "2\xe8\xbb@\"\x17\xee\xfbK6\x9d\xab\x10\xb90\x11" + - "\xc0\xa3n\x00\xdd\x9c\xf0\xcf\xbf\xed\x81\xaf\xf5\xff\xfe\xa1" + - "\xfd\xd5\xf7Pi\xfe\xaf\xb3'2\xaeg\xe4\xb6O\x01" + - "sW\x11\xfc\xef\x94\xc1\xff\xb8>>\xa9\xa3w\x0fc" + - "\x1eV(\xa6\x07\x8d\xc9\xd6\x9en\x94d\x8c\xa5!\xd4" + - "$\xa5\xc9sx2\xc6D\x1b\xee/w\xf0\xa8l\x91" + - "'c\xb0N\x8c\xca\x9e\xbe\x0a\x931\x90\xa3\xbb!9" + - "\xb0\x0a\x931zA7-\xd9\xb1\x85\x10:=\xb9z" + - "\xb025#3b\x0c\xb3\xca\xe4\x8ca\xcb^\xbab" + - "\xc5n\xd3-\x1e\x97w\x97\xb5\x0f\x17Km+\x97\xfa" + - "\xc5bn\xd9\xf2\xd6\xe3\xc6\xb1Eq\x1cZ8%g" + - "\xe9\x8a\xb6V_\xb4\xf4\x88\xe6\xe4\xa0\xdd\x8a\xe3\x96." + - "\xb3\x08\xdd\xf6\x97\x84\xa2%\x94\xb0\x17:\xac\x0f\xd3\xee" + - "$$\xbb@\xd3hv\x89\xa6\xa6#h{\x09\xc9." + - "\x01\xf9JMqX\xaf\xd0n!$\xbb\x12\xe4\xdd\x9a" + - "\xe2\xb0\xee\xd0\x9e#$\xbb\x16\xe4C\x9a\xe2\xb0\x1e\xd0" + - "`\xfa\x1c\x02\xf9\x19\x9a\xe2\xb0>\x1d\xcfs\x06\xc8M" + - "M\xa1\xb14\x90\xc8o\x14\xe4\x1e\xc8c1n7\xec" + - "\xc0\xfb\xf1BB\xc0\x86\x06n\xb1\x9f\xa5\xfd\x08Lj" + - "\x90_\x02\xf2\xc6F\x1c\xb8\xcb.\xe6$|\x92\xb5o" + - "\xda4t\xc5-\xbbNk\x06\xc5\xad\xa0\xb8\x07\x14\xd3" + - "\xa7s\xb7\xf5\xddxG!;_r\xc6\x0c\xee\xb6~" + - "\x10\xe5\x0f\x83\xfc\x09\x9075q\xb7\xf5\xe3\xf8dO" + - "\x80\xfcydL\x9c\xc9\xdd\xd6\xcfjH\xbc\x03\xf2W" + - "\x90\xea0.\xa2\xaf\xd8C\xaf\x81\xfc]\xa4RLp" + - "w\xf6;x\xfew5\x8d\x0eb\xf05\xc9\xd7\x97\x8f" + - "\xf0\xc1\xa2Q\x8df\x13Q\x85T\xa3)\x0a\x1d4\x03" + - "\xe4s0\xf8\x9a\xc2\xf5eYKt\x1e<\xd7\x02P" + - ",\xc1\xe8k\x9a/0\x8b\xa20\xd1/\x01\xf9J\x8c" + - "\xbe\xb6\xf0\xe8\xeb\x0a\x94\xaf\x04y7\xc8g\xcd\xe2\xe1" + - "\xd7\x8e\xe8C\x84d\xbbA\xde\x0f\xf2\xd9\xb3y\xf8u" + - "}\xf4*B\xb2\xfd \xdf\x0a\xf29sx\xf8u3" + - "\x9eg+\xc8GA>w.\x8f\xbf\xb2(<\x80\x09" + - "\xf2q\x90\xcf\x9b\xc7\x17\xb6r\x14,\xc3] \xdf\x03" + - "\xf2O}\x8a/l\xe7c\xfb\x8b@~\x05\xc8\xe7\xcf" + - "\xe7\x0b\xdbeQ\xe8\xe7+@~C4B}\xb7<" + - "\xac\x82\xdd\xf7\xba\x99M\x15\xfe@\xb7<\xdcixC" + - "\x06-\xb2^\xf7d\xcb\xdeI-\xa9\xd3=f\x9a\x86" + - "G\x19\xcc\xb6\xbd\xee\xc9q\xcb\xde)\xd5\xc3\x86\xd7\x93" + - "/\xb0\xae\x88m\x8d\x18N\x91\xe5\xd78v1k\x14" + - ",Ma\x0a\x13\x1b\xe9<\xdd\x14\x92\"\x86\xba\x11\xc3" + - "b\x1b\x9c.\x9b\xea\x8e\xcb@\x1f\x87\x06\xaa\xb5\xb4\xbd" + - "\xdf6,\xd2\xeeU\xdes\xa0\xa0^?\xf24\x8e)" + - "df\xa6\xeez\x1bKy=\xe21\xb8\x9dncd" + - "\x849\x8c'-W\xb7\xd1x\x9b\xe0\xcej\xb6u=" + - "\xc7\xb6\x0a\xbd\x96\x967\xb8\xed\xb6a\xa4\xcb\xb1]\xb7" + - "\xcbv\x98\x09\x02\xa5\xbf<\xe4u\x84\xdb\x11\xf3H\x1c" + - "&\x92\xea\xae@\x9f\xc2)\xb6\xb7\xd1\x8d\xeb\x15dn" + - "\x86\xd35\xcar\xdbi\xaf{\x0acy\x96\xaf\xa0m" + - "\xb3\x87\xe1b$c!+X5\xa1C\x84\xe9V\x9e" + - "9\x9d\xfc\x8dl\xd2MM\x8d\xc1(\xbc\x0e\xebug" + - "\xfb\xa6\xca\xa8F\xa1\xe4\x0e\xdae+\x1f\x19\xb4\x87\x0d" + - "kp\x1c\x11\x9c\xdd\xca7\x05m@A\xda\xb9JU" + - "\xf4\xd9;;u\xcd\xca#\xbc\xabrx\x97]\x1c6" + - ",\xd5\xfc-\x94\xdc\xb5Fa\xb4\x93\xea\xa2u\xec\x94" + - "\xf2\xf2\x83jWN\xd2F\x02\xedF\xcb\x18\xb1\x9d\xa2" + - "\xbc\xc7b\xd9\xf4\x8c\x92\xee\xd1\xd1^\x0b_\x96f;" + - "\x0a'^~\x9d^,\xc2\xbe\x98kc\x9e\xa25=" + - "\xd6\xd9\xbalh<\x82m\x82&\x9e\xed\xa8\x83\xd5a" + - "\xee\xe8z\xa6G\x82\x05\"hD\x9dI\xb7\x10\x19\xed" + - "q=\xa3\xa8{\xac\xd7\xad2\xe5\xfc\xbc\xc1\xab\x90\xa9" + - "5Y7u\xc8a\xc8vv\x94e\xa05\xe3\x06L" + - "k+\xc3\xb5i\x023a\xa5{%X\x9b\xce\xa1{" + - "+\xdc(\xc1\xdat1\xca1g\xedj\x95i\xedJ" + - "t\xd3\xa0)}\x93\xca\xb0|#\xca\x11\x03\xf6.\x95" + - "b\xf9\x0e\x94\xdf\x15\xe6\xb8\x05k\xd3\xfd\xf4W\xb0\x12" + - "\x84\xa6w\xb06=\x8e\xd7\x95\x14l\xc1\xda\xf4,\xba" + - "i\xa4\xdbE\xacM\xd5\xf4i\x94\xafL\xa9WqG" + - "\x81\xccl3\x82\xb8\xe9t\xb4\xb1;a%\x00\x1b;" + - "\x81\xb67\xe5\x0bS\x13R\xf6\xce\x00\xf9\x1c\x8c\x9bR" + - "\xbe0\xb5`\xfb\x04\xc8\xe7\x83Mn\x1ac\x18\x13#" + - "T\x05\x0a\xf5:r9fR\x1e\xf7\x1a\xd4\xe9N\xc5" + - "\xb1+t\x1b\x10`\xbaB7\xe2p\xa8S*(\xbe" + - "\x8cvfy\x83z\x8d\x83\xf9\x89\xd7\x18\xed\xa6\xc7\x1c" + - "\x96\x9f\xea\xec\x93\x1b\x04\x97\x88\x04\x97`\x96\x87\xa1\xa9" + - "\x98\xda\xca\xb3=\xdd\xec,\xe7\xe8v\xe6a\x95?\x0d" + - "\xb1o3y\x96\xd3e\xd6vQ\x1f\x1fd.\xf3\x88" + - "l\xd1^B\\\x80\xc0\x82\xac\xb2/\xc7x\xaak\x88" + - "n[vYX\x8c\x1b\x90\xf1LJ5\xae9\xce{" + - "\x056\xcc\xb1\xc8c\xd0k\x8d\xd8\xa4*\x88\xb3N\x06" + - "q\x02\xfb\xd7\x00\xd9\xa8F\x07\xd3\xc0\x0cJ\xfd\x86\x91\x9b~\xb7\xd29\xfd" + - "\x1a\x92Ln\xf1o{\xfb\xc5\xad\xcek\xeeoH2" + - "9\xe8\xdf\xd8\xf2\x87\x1b\xb2\xa7\xff\xf9j\x92L\xee\xf5" + - "y\x90gh\x82h%\xe6\x07}A\xa8\xedw\x8d\x8e" + - "\x8c8\x1dV\x9e\x82\xa9\xdc3\xee9T\x1f\x18\x0a\xbf" + - "\xff\xd5\x98\xd4pB\x90x\x00\xfd\xe3\xff\xf1\xbd\xe3^" + - "\xfd\xee\xcf\x96\xfe+Im\xc4\xe4\x85\x80N\xbb\x03\x13" + - ",\xc2\xc4\x08Z\xc7?\xfdIy\x11\x9a0K\xf1\x1b" + - "\x919\x0d3E\x0e\xc4F\xfc\xa6\x86@~\x06\xe6\x16" + - "$\xf8'{:\xe6u\xc8\\\x87\x98\xc8\x81\xd0\xb1\xfd" + - "\x19 7#\xe2\x13\x87o\xd6@\xf9(\xc8=\xccE" + - "H\x8a\xacy\xbc\xae\x09\xf2\xf1\x88\xb0J\xe1\x9b-c" + - "{\x0f\xe4gc\xde\xc8\x0c\xc1w\x8d\xb9\x112\x07\x02" + - "\x8cO\x9e\x03\xb17\xc8\x81@\xda\xef\xe4Ln5>" + - "\x1b\x819\xe4)\xcc?A\xb3=\xce\xad\xc6\xa3\x91\xaf" + - "\xfb(0>\x97\x82\xbc9!\xa8\xd8\xb4u\x81\x99\x8f" + - "fu\x8ar\xa3\xf1,4bw\x81|\x0f\x9a\xdbI" + - "n4\x9e\x8frinG\x9b\xb9\xd1x1\x9e\xff\"" + - "\x90_\x81Fu\x8a\x1b\x8d\x97!w\xf6>\x90_\x8b" + - "Fu\x9a\x1b\x8d\xd7\xa0\xf1\x1crg\xfb\xdb\x99c1" + - "\xb3\xc3!Z!\xfc,g\xd4\x04Q\xae1\xa4\xf3\xca" + - "\xf0\xa2q9(\x03\xcc\x7f\xf1=\x07\xcdKr\x00\xd2" + - "\x84\x1c\xb5\xa2v?o8\xaa5`x]v\xb1h" + - "\x10\xea\x85\xc7\x17\x0c\xaf\xd3\xd1\xad\x1c\xa1\xa3\x81lw" + - "Iw]c\x8c\xa9\xc7\x0d\xb2\xa2\xed\x11*#c\xfc" + - "\x1971\x92\xa9\xbc\x1f\xb1S\xec\xa7\x8e]b\x8eg" + - "0,\xfa\xbf\xfc\x07_\x98\xf3\xab\x13\xeex\x9f\x10r" + - "\"M\xd2\xcc\x00\xd8\xbe\x8a0I?;\xd0@)\xee" + - "\xa7)N*T\x9c1\x821\x96\x12LY\xff\x93\x13" + - "5\xf1\x13\xf9\xb6;y\xc2\xc8\xd9\xc5\xa2\x8e\xacI\xe4" + - "\xff\x0fW\x98\x8a\xa65\xec|\x9cqdG\x0e\xdb\xb6" + - "g\xda\x85^X\xd0\x94\x97\x92ur]6\x89\x17\x8b" + - "\x867ILA\xda\xcd3L\xaa'\xb8\xfa)\xf2\x95" + - "O\xe2Vf\x98\xb6\\Q\xde\xd3\xa0E\x13\x7f\x8d\xdf" + - "Pr\xd1<\x09\xd6\x9f\xa4\x0bp\xd7\x82\x19\x02\x01Z" + - "\xbf\xe6\xc9\x1c\xb4\x11\x87\xed8\xa5\\<\x04\x13P\x97" + - "@\xe0\xe2\xb1\x01\xe1\xcf\xe4\x16\x13\xaf\xf2\xaa\xa6\xa4]" + - "U\xc1\xe8\x1c\x18J:\x1a \x12\x8c?\x98,\x19&" + - "\xeb\xcb\xf0WT\x18J\x06\xca%\x18\x7f\x9d0\x94\x94" + - "\xe2\x01\xf4\x81\xd6\x0bCi\x07\xca\xa5\x0f4&\x0c\xa5" + - "2\xde\x8f\x02\xd2O\xb9\xa1Tm\xd0E\xc4\xac{\x0e" + - "\xca\xa5o\xb4\xb1\x81\xcf\xba\x17 n\xfbEaq\xc2" + - "\xb4F>\xeb^\x86\xbe\xcb+B\x9fi`)]\x87" + - "\xed\xb18\xe1v\xaa\x10c\xde\x86\xf1\xb8\xd0\xd0C\xd2" + - "r\xf9\xb1f\x10\x03!,@\x08\xe3\x0c\xd4\x08\xff\x0b" + - "\xed\x0e:\x12\xda\x10v\xd9+\x95\x15\xe7\x9c\xee\x951" + - "\xe7@\xb1\xb2\xf0\xc4\x83\xba\xa7\x12\x91\xeb9\xaf\xac\x9b" + - "}:\xc5w\xda\x91\xcbi\xcc\xac\x82\x94\xcf\xf7Q]" + - "hc\xb9\xa9\xb5\xeb\x98\xe6l\x0fi\x01\xaa\xad\x96\xda" + - "\x16\xc9\x06\x01\xfd\x15 \x7f\xd9\x85\x9e\xb8\xe59\x13U" + - "i\x0f\xf3\x94b\xbc\xc0.\xb9w\x9e\x8cC\x87v\x89" + - "\x1a\x86\x0e\x0b\xfc\x1e9RF\xa1\xc3\xb4\x87G\x8f\x94" + - "Y\x13Td=<\x0e\xb2\x03\x1a\x1dxJ\xa6,&" + - "\x9f\xec\x94\x99\x14\xb0\xe9\x13\x14n\x9a''\x86\x92c" + - "\xd8\x0e\xee\xe7B\xf6\xb8X\xc9\xc8\x07\xcf\x1e\xf3\xd4\xff" + - "\xf5B8K\x179\xc6\xc5\xa4\x19`\x0a\xdfY\x907" + - "\x10\xa4\x0d\x04\xfc\xf4\xa2~k1\xaf\xdf\xe2u\x12\xfa" + - "6t\x19\x9e\xde\xc9\xeb\xb7\x86\xd1e8\xd0\xc6\xeb\xb7" + - ":y\xfd\xd6\x91\xbc~k\x90\xd7o\x0d\x12\x127\xf2" + - "&kw\x99\xee\xe4F}\xfeg\x13#q\xc7\x18\x99" + - "\xd8-|\x11\xbe\xe7\xe8\xb9\xed\x9b\x98Cb\xc6\xc8D" + - "\x06\x7f\xedv\x98\xeb\xe9\x8e\x17\xcb\x97l\xd8\x0b\xb7." + - "-\xba\x9d\x84\xb2\xe0\xff\x0eB\xbd)\x9eM\xcenY" + - "\x9d\xa7\x01x\xf0\x1f\x9a\xa6\xa4j\x10,\xae5\x08V" + - "\xd5\x1a\x04\x8e:\x08\"\xb5\x06\x81&\x06\xc16\xe5\x85" + - "\xc3\xec\x02\xa3\xe0\xc9-\x92\x04\"\xa8\xc1H>{\xbd" + - "\x0cT\xf2Tq\xf1\xa2\xdb\x0b\x96\xeb\xca\x9f\xfe\x88\xa9" + - "\x17\xdcN\xc3#\x99\x11\x83\x99\xf9`b\x8d\xe5,;" + - "l\xc3L\x86/\x91\xc4\xadnV\x90\xf1\xc53\x8db" + - "\xd9\x1b\xed&\x1a+ ;\x86\x06c\xcbe\xe5\xbc\xed" + - "\xe8\xd4*\xb0A\xe6\x1a\xf9XY7'%15L" + - "\xd1\xab\x8a\xbbU\xf4\xae\xead\x1f\x82\xb7\xc7C\xbe1" + - "\xaf\xecV\xed\x05\x948_\xd8\xdf\xc5\xbd\x8a\xdd\x1f\xe4" + - "\x1aM\x9c\xa9\xb0\xc7\x07\xb9F\xe7\\/\xd3\xeb*\x1e" + - "b\xd2\x96\\w\x1c\x839\xfdtTwQ\xa9LX" + - "\xa3\xba9\xd25\x913I;\xabtP\x05\x0a\xca\xb2" + - "\xe5a\x18\x8415\xf2Z;\x0c\xa7pTg\xccp" + - "\xcbpw\xf3\xfa\xaf%N:\xfcG$\x99\\\xe7\x1f" + - "\xbd\xe9\xcb\xd7\x1c\xf7\xb6u%I&\xb7\xf9\xa7\xdf:" + - "\xf7\xad\x1b~\xfa\xd3kQ\xd3os:kB\x88\x8f" + - "a\x15\xc3b$\xbe\x9ey\xba/\xb8D`\xa7\xa3\x86" + - "\xbb\x95i#\xec\xbe\xa7\xb7\xc9\x188\xe5\xf5\xb5\xc9\x17" + - "`\x08?\xa3\xd1\x81WD\x10\x1bz\xef\xe5m\x82L" + - "\xe4M\x11\xc3\x86\xd1\xfa\xfab\x19\x17\xc7\x006\x8c\xd6" + - "\xb7@\xf8\x9aF\x07\xde\x15o\x04F\xeb;\xf0\x05\xbc" + - "\x1dp\x91\xf0Pw\xf2\x83\xab\x14.\x92\xdd\xc8\x0e\xd3" + - "\x9b\x97LS\xfcw\x0f\x89\x8f{\x8e\x1e\x92\x08\xe9|" + - "{\x9d\xf0\xcf\xeb\x19\xdb\xf2\xfd\xfdO\xec\x93\x85\xe3j" + - "'\xd0\x84\xec;\x81\xb8U\xe4\xe2\xb0\x17\x85\xb8\xa4{" + - "\xa34!\xbb=\x08\x84c\x15\x98c\x93L\x097\xb2" + - "\x15\x01\xa9\x9eqFE\xb4\xca\xd0\x94hU\xed\xf7\xac" + - "\xd4\xbbb\x11=F\\sk\xdd\xad\xff9\xe1\xff\x1c" + - "Y\xa6\x82\xa0\x0bAR\xce\x81\x13B\xc3\xe524P" + - "\xa4\xc7&0\\\xae\xc4bH\xb9\xc0\x07\x1e\x9e\xeb\xd0" + - "P\xb8\xb6\x06\x97\xfe\xba\x0aON\x94r\xc3\xe5\x0e<" + - "\xff\xada\x10\xb5\xae\x81\x1b.J\x10\x95{x\x1a\x03" + - "\x0f\xcfU\x15\xe4\xfbA5dubM\xc0\xe8\xfd4" + - "\x1a:\xa1\xe7\x87\x0a\x07\xcf\xb3\x18\xbb}J\xc6\\g" + - "p\xbb\xe5-\x8c%\x871\xd7\xe4\xf4&n\xb7|\x80" + - "\x97\xfd\x10\xe4\x0d\xe8\xe1\x99\xc9\xed\x96:\xdc\xfd\x85\x9e" + - "\x9f\xd6\xa6\x97\x84\x8b\xa7\x09\xb7ya\xd859s5" + - "\x8f=$\xb1\x9c t\xfddpr\x0c\xeb\x1dL\xdd" + - "3\xbcr\x9e)\xe5\x1daf\x0e\x98(\x81L7'" + - "\xb5\xcb\xb8\x15\xe9\xe4\xc3Lw\x0c\xab\xc0g\xce\x90D" + - "\xd3v\x8c3m\xcb\xa3h\xd6\x94\x1d]\xcbI/L" + - "%\x8f\xd6z\xc3\x8c\x99\x86K\xebH\x84\xd6\x11\xda\xee" + - "\x06\xd9@\xe1\xb0\xe1{\xb7\xf8\xd8)\x12&-\x08\xb4" + - "\x8e\xc1&)\xa7\x9b\x94_%7\xa1d1\x88\x1b\xeb" + - "\xa0B\xd5\xad\xde >CG.G2\xa8\x0b-\xb9" + - "Q\xdd]c\x8cO\x0a\x12\x90v\xc63#\x0f\xee\xe4" + - "\xa9\xca \xee0\x99\x93\xf1\xb2\xc6\x99*k&7\x15" + - "\x8eh\xe3%\x95\xbc\xd4;\xb9\x98\x90\xb8e[,\xe3" + - "\x16u\xd3\x8c\x15\x8d||\xa4l\x9a\x87\\\xb9'm" + - "HbA\xd0v6\xdf{4u\xca\x8c\x89\x906:" + - "x\xb9\x9f(\x0d\xba\xa3\x9c7\x86M\x86\xa9,\xdc." + - "X\x82\x0fr\x16\x7f\x902\xb7y\x8a\x83\xf8 h\x01" + - "E\x93:\xb7yN\xbf\xb0\"L\xba\x8d\x87I/D" + - "\x9bg`\x1d\x86I\xd7\xaf\x13O\xde\xce\x89\x95B\xf2" + - "#BY\xbb\xc3F\xca.\xf3w\xea\x8e\x05+%\x89" + - "\xd9#^\xf0\xab\x97\x8aDWFH{\xc9\xb1\x8b%" + - "\xcf\xe7\x7f\x06\x19\x89\x97\x98\x1e\xfc\xec6(\xcf\x05b" + - "y\x9e\x8e-\x9e\x84\xc0\xce\xb5d2\xaf\x82\xbd0R" + - "]\x1f\xdb\xce\x0bdq\"\xbb\xfa\x17\xa7\x97~{G" + - "\xe2\x19L\x1d\x09*f\x11\x90k`m8\x8f\xbd\x8e" + - "\x1b\x0c\x99d\xa1\x89y\xec-\x9c\x97\xde\x04\xf9\xfb\xc1" + - "\xbc\x04\xf3\xd8{\x98\x94\xf1.\xd5\xe8`$Ba\xde" + - "\xf3\xf7=w\xf5_\x0f|\xb8\xf8I\x92\xfa\x08\xf3O" + - "`\xea\x89\xe2\xa9a\xaaz\x0dN\xf1.L13\xf9" + - "L\xf5\x0e\xcel\xf2\xcc`L5L:s\xb2)\xc2" + - "g\x9e\x8fp\xe2\xc4\x19\x06}\xc5\x8d3\xb9\x7f\xa9\x05" + - "kl\xc2\x09#\xd9\xf06\xf7\xff\xcc\xc5Z\x1dY\xc7" + - "4M\x94l\x1e\x8d\xb51\x0bA\xbe\x1c}\xd4\xa2f" + - "\xb3\x15\xdb/\x07\xf9\x89\xe8g\x135\x9b\xabqBB" + - "\x17\xdeZ\xf4\xa7\xd5s\xffO\x0f\xcel\xdd\xa1\x9f\x8d" + - "\xa6\x04\x15?\xca\xb7\x82|\x14\xfdf\x0b\x05\x15?N" + - "x\xd2\xcf6\xa3\x85\x07\x0d\x0d\xbc\xae\xf4\xa7Ef\xf1" + - "\xa0a\x95?m\xd2\xea\xcb\x04\xd2\x93R.\xe6{F" + - "\x11\xec\xea\"\x89\x97z\xec\x91p\xb3Q\xe1~2," + - "\x8f\x15\xfa\x0c\x0b\x13D\xc4\x16#c\xc0\xa8\x90\x08\xb0" + - "\xf24Y\xe54X.7b;\x84\x16\xab3Q\x0a" + - "\xbaa\xc9Y\xd4(\x8cv\xd9\xd6\x18\xe5\xfb\xb9\x93t" + - "\xcd\xb0&\xc7\x1eOr\xd8\xc4\x1aG\xcf\xc5\xd1Z\x08" + - "\x9d\xe2\x98:y\x92C\xb9\xd234E\x19$R\x92" + - "v\xab0\xa4\xe6\xa0\x04(R0-2\xb7\xabz\xba" + - "\x15]\x97%\x19\\\xc5CK\x85\x17#\xd1\xb8\xfcB" + - "D\xd6\x0d\x1b/\xd9XH\xb0\x89;\xc9\x99fyJ" + - "\xf1\xca\x8e2s=\xf4\xddT\xfb@*\xcd\x8aN\xdb" + - "\x16i)9$4\xe6y#\xdc\xae[\xb4NzW" + - "\xd0h\x80\xc9\xa9u\x9dB\x9ci\xea\xaewr\xd1-" + - "\xa8\xc0\xc0 \xeb\xaf\x92\xd5v\x02}\x82\x9c\x19\xce\x82" + - "6\xb00\x9c\x03\x1a1\xf1Kf<\x068/I4" + - "\x06f\xe0\xa7\x17\xe4\x1a\xc3\x1c\xd0\x82\xc6@\x98\x09\x19" + - "\";T\xe3\xc2\x04\xc8\x0e\x8b0\xc1K\xe2\xc2\x04\xc8" + - "\x0e\xadx\xdd\x10\x17&Dv8\x1e\x8d\x8a\x13\x02\xe4" + - "\x08*\x82U=h\xb2H\xe0\x88\xc0\x94\xd9\x8c\xf2\x10" + - "8\x826R\xea\xff\xf5\xf3\x8b\xca?\xb9'\xf6k\x92" + - "*\xc2\x9c\xe4\xe7l\xcb\x85\xb5\x91'\xd2\xf7\xe6\x09\x8d" + - "\xfb;\x1bzn:\xf6\xea\xd8\xb9\xc1\x8a\xad\xee\xd5\x82" + - "@\xed\x1a*H\xdf'\x94\xec\xce`\x8fBbVA" + - "\xda\x1e\xa1\xb4\xdd\xe2\xd5f\xd5\x0a\xdc\x97\xa1\x9fe*" + - "\x0d\xd6\xa1\x05\x95\xb6\xae\xee\xf5\xdbnU\x05\x11H7" + - "1\xb3\xba\x86\xb4&\xcd\xebTh\x06kw\x8a|\x1a" + - "\xcc\xd3\xcd~q\xfd?-L~\xe1!\x92l\xbc\xcf" + - "\xdf\xcc^9\xea\xe6\x81\xcf\x7fL\x92MW\xf9\x1d\x96" + - "\xc7,K\xcf\xd2r\x899c\x86k\xb7\xf3\xca\xb1@" + - "\xd1O\xed\x9d\xbc\xeaJ+\xbbj\xe1\xc0\x16\x85\x0a5" + - "\xd8\xcf\xa8T\xa8\xe1v\xf0\xc6N\x15dIl\x07o" + - "\x86\x967ht\xe0v\x18B\x0d|Cs\xdb*\x05" + - "y\xa9\xae\x91ohT\xd6T\xdf\xb2\x0d\x97\xf53\x87" + - "h\xeb\xb3ae\xb5^\xc8uY^\xe8\xc2\xd4\xf9\x83" + - "\xd3\xb8|j\xfe\xee\xdb\xf5~x\x16\x1a\x97= \x14" + - "\xdb\xf4b\xaf\x15\x0e\x0ba\x96\x06\x83d\xea\x18q\xb0" + - "\xad\xe0H\xb4\xbc\xa7\xe9\x87\x03'?v`\xfd\xdf\x93" + - "d\xe3*\x7f\xfeO\x9e\x1by\xeb\x83O\xff+I\xd6" + - "\x0d\xb7\xf3\xdb\x0a\x8b8H\x8cY\xde\x80\x19~\x9f\xaf" + - "b\x19\xeb+\xb0$\xbc\xad\x96\xe6\xbe\x85e\xa3o\x83" + - "\xfcC\xb54\xf7\x03l\xff>\xc8\xa3j\xa6\x13\xd5\x86" + - "\x09\x19\xd44\x9a\x9d\xa1&:5b\xe2R\x03\xc8\xd3" + - "j\xa2SR\x83\xcf0\x0d\xf2\x05j\xa2\xd3a\x1a|" + - "\xb6\xf3\xb5 R\xd3 \xbe\xcf\xa3\xf1<2R\xd3(" + - "\x82\xc9\xc7`\xa2\xd6R\x90\x9f\xa0\x09_(\xec5\x8e" + - "\xc7<\xa1\x13A\xde\xa7\x09_(\xac\xf8\xbdx\xdd>" + - "\x90\x9f\xa6\x09_(\xec56j\xf7\x11\x92=\x0d\xe4" + - "yMT\xdb\xc2^C\xd7~\xa6&^\x81\x9d\xd1\x84" + - "yW\x18\xb0\x02\xf18f3Q\xbe\xd3(c H" + - "\xe6c%\"\"`\xa5\xc142\x0e\xf2\xf3@\x9e\x8c" + - "\xf0\x80\xd59\xda\xf5\x15\x81\xa3\xe6\xa5\xbch\xf7b\x0c" + - "@\xc9\xc0Q\xaa\x95\x17\xed^\x86\x01%\x198J\xb7" + - "\xf1\xa2\xddk\xb4\xb6\x8a\xb4\xaeX\x137X\xae\xc3\xdb" + - "\xbf\x09\xe4w\x81\xbceY\x9a\xb6P\x9a\xba\x03\xcfs" + - ";\xc8\xf7\x83|\xd6\xf24\x9dEi\xea^\x0cL\xc9" + - "l\xaf\xd9\x1a7X\x1e\xc4\xee\x7f\x00\xe4\x8f\x81|\xce" + - "\x0an\xb0<\x8a\xaf\xeb\x00\xc8\x9f\x02\xf9\xdc\x06n\xb0" + - "<\x89\xede\x16\xd8\xbc\x99\xdc`y\x16F\x89\xcc\x02" + - "\xf3K\x98\xd7c[$\xde\xd3\xd5\xb3\x86&\xe4\xd0\x0d" + - "\xf0\x82E\x03z\x12\xb3\xf3\xcc3r\x18Z\xa9n5" + - "\x16\xe4\x1cMu\x9a\xb0A\xec\x14D\x80\x9cR\xdf\xce" + - "\x83\xb25\x9a\x08\x18WA\xba\xc0\xc6\x0c\xadf3\xdb" + - "10;\x08\xc1\xde\xbbz\xd6\x90\x83\xb4!\xed\x86m" + - "\xd5\xbe!\xdd*\x94M\xdd\xd9D\x83\x9c\xa5\xccT\xf7" + - "\x15 \xb5EX~\x838/?\xebA{\x8a\x06\x1c" + - "\xdc\x1a\xcb\x1f\xeaa\xa1i;\xb4\xad\xddT\xdciD" + - "\x9c981\xa35Z\x87\xfb\xae\x902\xb8\xe4\x82\xd5" + - "\xb5\x81dF\xd4\xfdX\x90\xd1\x1e\x97\x13\x9b0\xa3\x0e" + - "\xbac\xf6\x0d\xabT\xf6\xdc\x0d'\x13\xb5\x18ZTy" + - "o \xf4\xe4P\x98)\x94\xdc\x0d'+%\xcd5{" + - "\xb1\xa7\xab\x87\xd6\x1aN\xdc\xc8s+\xce(\xf9c\xc2" + - "t/.\x07\xcb7kX9\xd2\xce0\xe3\"\\\xa1" + - "\xd98Z\x9ec\x94\xcb]\xe9\x8c\x84C\x86\xec5\x06" + - "iw\\\x0f6\xe1a\x16\x88\x0a\xb0Pk0\xd4^" + - "4\x04\xbab\x00\xae\x88\x15\x00`\xa6)\xc4\xe6\x17\x12" + - "2\x90\xd0\xe8\xc0\xfcH\x18Q\xe9\xa2\"\xb7[-\x88" + - "\xa8}\x85~\x01\xeb]\x85\xf6w\x94\x16Mt\xf2E" + - "\xf6\xad\xfb\x14_ \xed\xe2\x8b\xec\x07w\xaa\xbc\xc4\x91" + - "n\xbe\x06\xd4\x81\xcd5\x88\x09?T\xd4l4\xa2%" + - "\xe9TX\x92\xd1\x19|\xeaN\xa2e(\xe9\x8a\xeb\x9a" + - "\xf8\xd4=\x17\xf7|\xd2\x92\xac\x17\x99\x9f\xd5\x96dL" + - "\xccM\x8b\xb0\xbd\xb4$\x1bV\xf3\xb2\xb2V\xbcnh" + - "I\xfa\x05\xddE\x14\x0f\x9ac%\xcfv\xbaY\xbb\xc7" + - "**n0\x0a\xc1\xf2Yj\x14,\xdd\xecf^\xa6" + - "B\xdf>\xaa\xbb'\x95d*|\xa1h\xea\x16\xec\x9e" + - "3\xf9\x1e\xc7q\x0fA\xba_v\x87\xd1\x9c qL" + - "\x10\x8c\xfb;\xafX\xf2\xfd\xaf\xac\xd8sS\xf0\x81\xb8" + - "\xfa\x08\xf3&\xfau\x12s\xf4b\xe8\xbf\x0f\xa5qG" + - "/\xb6U\\\xc3\xd3M3\xa8v=\xb8\xf1q\x8a@" + - "e\xe7\xa0\xec\xc7v\x1b\x0e\xcb\xe0\xbf\x88\x83\x89VW" + - "\x07w\x85\x1c\xcf+\x92[y\xc6\xf8\"\x9e1~\xf4" + - "\x16t\x85\x1c1,\xfc\x1cq\x93\x8dx\x19\xc7(\x8c" + - "z\xbe\xeb9:\xfcC\x08\xf1]\x04\xf8\xeecD\x1b" + - "\xf1\xc4\x8fA\x83\xc4\xa0Ym\xdfD\x96Y\x19\xc4\xdb" + - "G\xd7\xc4<\xed\x8f?8\xfc7\xcf\\\x1f\xf8X9" + - "\x12\x7f|h\xa2\xc4\xa6\xe0\x92\x0f\x0d\xc9cV)d" + - "\xf2\xde\x04\xe6M\x84\xa7\x13F\x9b\x8bo\xf5\x10\x01E" + - "\xa5D\xdda\xb5\xaa\x08\"\x84\xb46E(!\x03i" + - "\x8d\x0e,\x88\x04\x9f6\xcbk\x15\xc7\xd6\xaa/?D" + - "|.(\xc6\x95\xe1\x96\xb8wlv\x13\xbc\xa3\xf3B" + - "\xb3\xefb\x0d\xb6_{`!\xde\xa7&\xb8_\x8a\xf6" + - "\x9440D0\xab:3\x05a9\xd1\xc5\x8c\x06\x83" + - "40\xa2\xc2?s\x07\xb6\xbf\x0b\xe4\x0f\xa0\xdd'\x88" + - "\xf3\xef\xc7\xf6\xfbA~\x00\xed\xbe\x18\xff\xe6\x1f\xc1D" + - "viH\xc4\x1a\xb8\xddWmH4\xd4\x89$B\x94" + - "\x87\x86D\xe0b~\x19O\xf3\x0a\x88\xdfFs\xb0^" + - "\xb8\x98\xf1\xb2o\x82\xfc}4\x07c|\xeex\x0f\xed" + - "\xb2\xb7A\xfe\xa1&\x0ax`\xee\xf8\x00\xed\xbb0\xfb" + - "\xbc\xa9\x8e\x9b}\x1fi\xbf\xaa\xc8>\x9fY\xcf\xcd\xbe" + - "\xa6(\xd2\xf0\x82|\x01B\x8b\xc5\xb8\xd9w\x18&\x8d" + - "\xcb\xe4\xf3D\x037\xfb\x16EaJY\x08\xf2\xe5\x98" + - "\xdd\xde\xc8\xf3\x94Z1\xd9[&\x9f7O\xe3yJ" + - "\x1d\xd1\xff$$\xbb\x16\xe4C\x98\xdd>\x9d\xe7)\x0d" + - "\xa0\xfc4\x90\xe71\xb9}\x06\x9f\xe2tL&\x1f\x05" + - "\xb9\x87\xc9\xedM\xdcO\xb5#\x0a\xe6Z\x09\xe4\xbb0" + - "\xb9}&\xf7SMD\x9f#${6\xc8/\xc2\xe4" + - "\xf687\xfb.\x88\xee\xadH>\x9f\x93\xe0f\xdfe" + - "Qd\xcc\x06\xf9\xd5\x98\xdc\x9e\xe4f\xdf\x95\xd1A5" + - ")=9\xafYTma2\xbc\x84\xac\xfbT\x8a\xfb" + - "\xa9n\xc3\xf6\x12\x9an~\x9a\xfb\xa9\xee\x8e\xdeR\x01" + - "5w\xd8t^\xb5\xf5`t[\x05\xa4\xdc\xe1-\xbc" + - "j\xebQ\x84R\x93\x90r\x99F^\xb6\xf58&\xc9" + - "K\x88\xb8\x05ky\xd9\xd6\xb3\xd1-*\x14\xdc!v" + - "\xe7\x99^+\xcf\xc6\xc3\x1dz\x80\xacAe\xf8\x9b\xc6" + - "e\xbd\xbe\x98\x86\xab\xf07\xc2\x93\xdbv~\xc3\xb0\xcb" + - "\xa8\x88\x9f\xbb2V/\x17\xf7\xb8^`\xf2\x90\x92\xc3" + - "\xf2\xccc9\xca\xc1\xa3\xc6tj\xcayz\"g\xb2" + - "\xaci\x90\xf6R\xe5\x04^\xb2]\x0f\x8e\"\xed8A" + - "\xcbhGqr\x81?MH\x80\x01IS\xe6\x18\xcc" + - "9\x85\xc4a\xe7\x1bny\x9d\x91>\xdb\x0d\xcf\xb5\xdb" + - "\xd4=\xe8\x9fp\x91\x09\xa6\xb0\x882\x01\xa1\xc7-\xa6" + - "\xba\xe3j\xb5\x82'+\xc4\x1c\xdd\x94+S\xd0\x0a\x8c" + - "\xbd\x8d\xa2\x9a\xd4\xf2&\xc8\xa4\xf3\x90L\xb6\"\x0a\x13" + - "\x1e\x89b\xf5P\xa2\xc4]x\xabHE\xb9\xd7\x1aG" + - "\xe7\xeb\xd9!\xda\xf5Z^\x86\x15\xd4\xbbU\xdaU\xde" + - "/\x9d\x98t.\xca\xf2|]\xafu\x95\xca{\xd6\x14" + - "\x98e\x99\xf6.r\xcei\x08Z\xb1[\x84\xec\xc3\xb6" + - "ad\x9f\xcaG\xc9\xdb\xa5\x92\xc9\x9c\x0e*L\xfb\xea" + - "\x97b\xb1j(\x8b@F\x83\x1b\x8a\x1b\x15\xb8\xcf\"" + - "bN\xe2\xa3\xba\x1b\xba\xaa\xdaG*q3J\xbac" + - "x\x13=\x0eulG@\x91\x85c\x11>\x86~\xdd" + - "1\x88\xa6\xe4\x16~\xf2\xca-\x91J\xa0\xf1\xb5m4" + - "\\\xdb\x1eE\xef\xfd\xc3\x11\x98\x0d\"\"\x9a\x0d\xf2\xc7" + - "\x11\x81\xeb\x890;TxHS\xcf\xa2\xab\xe3y\x90" + - "\xbf\x16\x11HDZ\x0d\xd7\x88&\xd6\xb6j\xd7HT" + - "\xb8\x1c?\x88\xc0,\xf7!\xc8\x1bpmk\x10\xf6," + - "\xfa\"f\xc0\"3\x07\xd7\xb6F\xbe\xb6\xb5\xe0\xa2$" + - "} \xc1\xdav\x18\xca\xa5\x0f\xa4\xb1\x9e/nG\xe3" + - "\xa2$\x8b\xd2\xa6\xcd\xe4\x8b[uQ\xda\xf4\x06\xbe\xb8" + - "\xad\xc05r9\xc8O\xc4\xc5\x8d\xa3)\xa5Vk\xb0" + - "jt\x83\xbc\x1f}\x1d\xf5|u[\x8frY\x946" + - "3\xc6W\xb7\xd3\xd1\x89\x90\x07y\x09\x9d\x1d\x0d|u" + - "+\xe2\xe6_:A\x12\x8d|u+cIW\x98%" + - "KE\xe9\xd6\xf9x\x9b\xd2\xe4\x08\x16\xb7KQ.M" + - "\x8e`q\xbb\x06\x1fW\xfa4\x82\xc5\xed:\xf4]H" + - "S$X\xdcn\xc6\xcb*>\x8dF\xbe\xb8\xdd\x8br" + - "\xe9\xbb\x98=\x93/n\x8f\xe2y\xa4\xc91'\xce\x17" + - "\xb7'\xb1\xf2\xec)\x90\xbf\x84>\x8d8_\xdc^\xc0" + - "\xee|\x1e\xe4\xafi\xff\x9fY4\x0a%\x17>!\x8f" + - "N\xf48\xf8\x89!\xc8M\xf8\x85\xf1\xdbZ\x1baX" + - "\xef\"\x9a\xf0\xaf\xf0\x10\xcbN\xed%`\xd2\x9c\x7f\xb0" + - "\xd5i\xcaE\xe8\xbf1\xad~\xd2i\xfa\xff\xd9\xf4\xfb" + - "\x89\xd6\xcd\xff\xe9$\x1d\xcc\xa9\x11\x98R\x11\xc9\x1d\xf7" + - "\x9a\x05GS\xb7\x1c\x93\x1b\xc9\xb8V\xd0\xc5\xff\x9d\x09" + - "}*c\xa2v$\xaa\x9f\xb3f\x1e\xdb\xd5\xbf1\x03" + - "\xbd\x8e\x89[J\xe6\xd1*5\xf3(\"2\x8f\x16+" + - "Im\"\xe4\x93|v\xb1\x02\xc9!6\x16\x95\xf9H" + - "bW\x91|y\xb1\x0a\x12U/@\xa2V\xa9IJ" + - "|?\x91|\xfdH5I\x89o&\x92ou\xca$" + - "\xa5\xf6\\\xa9|J\xb9\x18x\x8e\xe2e\x97\x85\xc9\xae" + - "q\xcb\xc8\x85\x81\xc0v\x17sBC\x9d\x917\xa5\xce" + - "\xb0w\xeaF\x18\xc6\x8b\x19\xce\x8e0\xf3\xd4\xb5G<" + - "\xe5\xf7T\xa8\xf0*\x10\xbb\xa9[\x95`y\xa6\x16\xa5" + - "M\xb5\xdc\xf44\x1ex\xe9\xdb\x08\xc9\xbe\x16z\xe3g" + - "\x8a%\x8d\xe2\x9c\x1a\x85\xb9*\x11l\xe3`Ik\xc2" + - "9U\xba\xe3\xa7\x8b(ZR\x03\x838\x01\xf2\xf9\xb8" + - "T\x88%m.\xca\xe7\x80\xfc(M\xd0\x1f\xc0\x92v" + - "\x04\xca\xe5R\x14\x8b\x06K\xd1U\x15KQ\xa2.X" + - "\x8a\x06+\x96\xa294X\x8a`#t\x02\xc8\xd7\xe2" + - "\xdc\x1c\xe1KQ\x0f\xee\xcb\xd0}\xbf\x15\xb7\x9b\xd3\xf8" + - "R\xb4\x19\xdb\x87n\xfa\x00\xaaY\xc7\xc7\xda\x0a\xe2Q" + - "M\xd4\x89\xc0\x92\xc3P.\xcb\xa9\xe7F\xf9\xd2b\xe0" + - "\xeeT\xae\\\xf53\xf9\xd2R\xc6]q\x09\xe4\xbb\xd0" + - "M\x1f\xe7K\xcb\x04>\xaet\xdf7\xd7\xf1\xa5\xe5\x1c" + - "\\\xa9\xcf\x06\xf9E\xc1J\x8d\xfb&ts\xcb\xa5n" + - "Z\x8c/-\x97b\xfbK@~5.u\xc2]~" + - "%\xba\xfb\xe5R\x17M\x88}\x13v\xc3\xd5 \xbfI" + - "\x13\xa8\x19\xb0o\xba\x11\xe5r\x09L7\xf2}\xd3\xcd" + - "x\x9f\x8a\xbb\x7f\x1a\xdf\x1f\xdd\x81\xdd\xa6,\x8d\xd3\xf9" + - "\xfe\xe8^|-\xd2\xdd?o!\xc7H~\x10\xef?" + - "\\2\x03z\x96*\x9c\xccL\xbe\xdf6\xab!\xe6+" + - "A\x8d*\x13)w\x8fU\xa1\x18\x09T\xa3\xf5DS" + - "B\xfdR\xa8K\xc7\xe76\xe6l_\xa3\xe7<\xa2\xc9" + - "\x9c\xf4\x90\xa6\x9az\x8c\x03\xad\xa8T\x18\xa6n\xb1S" + - "\x8d\xbcG\xa8\x9cr\x0b%w\xc8\xd1\xb71\x92\xc9y" + - "\xb63A\x13\x1f'\x96\xbe\xe7\xdc\xfe\xf1E\x02\x81\x8b" + - "\x8dU\x92\x16U\x13P\x8a\xfb_C2eO\xc1\x04" + - "\xdc=\xd6\xe5\x94a\x91\x0c~\xeb\x95\xbfC2]\xca" + - "\x9c\x0eL\xb2\x97\x89\xa7\xf1\xb1\xf5\xcac\x8euq\x97" + - "+\xd1\x14\xc4\xc1<\xcb1s\x8d\xed\x90\xf8P\xd9\xb1" + - "\x94\xe4S\xb7\x8f\x8dx}$\xa6[L\x95\x0e\xa2#" + - "-\xde\xa7\x8a\x8bzId\xbcJ\xb0\x91\xb1\xac\xa7;" + - "\x9e\x04\x8e\xaa\xf8\xc9;w\x13\xd2\xc7H\xd7&\x0a\xbb" + - "t\x8bd\xd0\x94\x90F\xbb],\xf6\xban\x99(\x15" + - "\xda%\xce+a\x92\x98\xe1M\xd0\xb8\x7f\xe5YG\xcd" + - "[\xfd\xab\xbd\xbf\x08\x8c\x9d\xbf\xa0\xc6\xa3\xbf\xb7[\xe2" + - "\x10\xaa\xb9\x05\xf0\x19D)\xccrj\x9ed\x13\xe6\x10" + - "H\x8fp\x10\xbb\x9c\x8b9\x01Jn\x81\x16\xe4\x16l" + - "\xa9\xcc-\x88\x06\xb9\x05\xcd\x84d\x8f\x02\xf9R\xb5\x12" + - "\xf6\x18\x94KOq\x10\xbcTX)V\xaa\x95\xb0+" + - "\xf0>e.B\x90\\p<\xa6\x1fI\x92\x9a\xa0\xc0" + - "\xa3\x83>\xa4\x92\xd1T\x15fp\xe4V\xc3*\xd0\x0e" + - "\xab`\xb2nV U\x00\xb9\xa0\x1b\xd4=TU\xe2" + - "\xd6\xf68\x8e\xfa\x05\xd5\xac\xea\xf8\x8bj9\x82\xebE" + - "\xc4\xbd`\xe0\xa0\xe2\xba\xb5\x1d\xa4*\xc0\xa5\x9a\xaf\xd7" + - "\x17\xbe\xdc:\xd8\xc5Ih\x9d\xe0\xdd6\xe2\xe6N\x96" + - "\xfd\x06\xef\xb6\x09\xe52\xf73x\xb7I\x94\xcbr\xe0" + - "\xe0\xdd\xb6D\x8e\xacH\xf1\x0a\xde\xed\\\x94\xa7A\xbe" + - " \xa2\xb0\x1f\x1c\x86\xf29 ?\x0aS\xad\xa6\xf1w" + - "x\x04\xa6r-\x00\xf9\x92\x88tD.\xc2\x8c-\x99" + - "\x11\x96x\x90/x\xad\x98\x81\xb5\x14\xe4'`&\x9a" + - "\xf0\x14\x1e\x8f\xa7\x91\xc8\xd6\xd3\xa6\xf1\x95\xad\x03\xe5\x12" + - "\xd9z\xe6C|e\xeb\xc5\xf3\xcb\x0a\xce\xf8\x0f\xf9f" + - "j\x00\xf7\xa6\xb2R\xb3a\x09_\xd9NGTg\x99" + - "A\x16\x9b\xcdW6\x86\x8f%3\xc8\xa6'\xb8\xa7\xcd" + - "@{CVj&\x93|%\xd9\x81r\x89V\x0d+" + - "\xe1\xa7\x11\xadz0@\xab\xde\x17\x89\xd0x\xaeT^" + - "\x1a\xe2\xd3\xe7J\xe5V\xf5G\x9b\xfacY\x08i_" + - "da\x98#V(\x95\xc3\xff\x87u\xe9N\x18\xd6=" + - "\x8f9\x13\xfd\xa4\x9d\xe3\xa2\x85\xfb\x10\xa1\xc8\x92\x0c\x8f" + - "\x1c\x06\xc5,ewx\x83e\x1a\x96:3\x89\xb6]" + - "\xa4\xbd\xec8p\x92\xc0\xb2\x16\x8aM\xa4\xdd6=\xbd" + - "\xc0\xa4\xc9=\xaa;\x05\xc3*L\x9a\xf7\x84\x9cv\x87" + - "8\xb7RW*o\xc4\xba\x9a\x00\xc2-\xd8\x0c\xc6J" + - "z\xd87\xc1%\x87H\x9c\x15K]\xf2k-\x0e\x1b" + - "\xcc\xf2\xaa\xc5\xd6X\x91\x0d\xb1b\x89\xd0\xaeO\x06c" + - "\xac\x04\xe6\xd6\xe8e\xd3Sj,\x04\xcf\x0f\x0f\xd8\xb4" + - "\x0cb\xc0&9(b3\xfe\x08\xb4\x1ebEBK" + - "\xfc\xff~\xe6\x10Z\x9c\x8a\xdc\xa9:3,\xcc\xc6\xcd" + - "\xf2\xf7Q\xc5\x94v\xae\x9a\xc5#\xf6\x06\xd7-\xae\x95" + - "\xc5\xb3\xf8\x90Y<\xa2\x92\xea\xb6N5\x8b'\"\xb2" + - "x\x8eT\xb2x\xfe\xd2<\xad \x02\xf4\x8d\x8bo\x8f" + - "\xce\xd9\x7fe\x98\xcf\x13\xa6e\xff\xe1\xca\xef\\\xbe\xec" + - "[\xbf\xfeCPR\x1b\x04\xb7\x83\x81\xeb\xd9;'%" + - "\x18\x7f\x12\xb6\xb9S\x05\xc0^nTa\x9c\xe3\x11\xdb" + - "\x19a\x1f\xf6\\H\xc8\xc0Z\x0e\x08\x15\x06\xb0\x06\x1c" + - "B\x06\xfa5:\xb0U\x012\xdc\xbcW`Q\x8f\xfe" + - "7\x91\x059\xeb^\xaf\x85\xc5y9\xcf\xb0h\xe1\x10" + - "\xee\xba\x1adW\xd5e\xa2\xf5|O\xb6\xa8S\xc6\xe1" + - "(\x07\x10M\x1e3L\xc8\xc0\x12\x8d\x0e\xac\x8c\xd0\xdd" + - "\x13\xfaNX\xcb\xfe\xe2\x10\xf8'\xf5\x1fr(\xbc\xcf" + - ".\xf9\xdf\xbf\xdd\xb2y\xc6;$I\xe7i\xd9M\x15" + - "\xccT\xab\xa6`\xa6ZUa\x1c\x04\x91\xb2c0\xe9" + - "Y\x1a\x07Z\x03_\x88Z1\xf1p9\xc8O\xa4J" + - "\xa4l5\x16Q(\x8ctb\xeb\xd5\x8b\xe1\xe8\xb5 " + - "\x1fR\x13\x18\x070y\xba?\xccT\x0c\x8a16\xd3" + - "[*\xaaZ\x03j*\x86\xd7U\x98\xea\x045\xd5\x0e" + - "\x84\xa2\x0c\xabN\x03\xb8\x8ds`\xe3!\x99\xaf\xe4`" + - "\x0f\xd1\x89\xc5WP\xe9\xe7\xad\x1e\xfb\x81\xe7\xa9\x8bN" + - "\xe4LvJ\xb98\xac1\xa7\xda[v\x0a-\x17\x87" + - "\x99\xb3a\xa4;\xa6O(!\x0a\xc34\x0d\x97\xe5H" + - "\xdc\xb6\xf2nE\"r5\xc5\x00\x02\xf3\x0e\x19E\xca" + - "j{4@\xbd\xc6a\x94\xfb\xe4:\x0dMw')" + - "#\\Y\xcbi\xa4\xb9cr3\x10\x0e\x91*\xe4\xf4" + - "\xaa\xf2.6\\.\xf0\xbc\xfa*T\xb7-U\xc9\xb9" + - " l\xdd\xa2$\xe7\"\xb3\xea\x10\x1b'\x9a\xd7*\xcb" + - "\xe0\xa5\xb0mR\x85\xe6\x94s\xfdZ\xdd\xb1\x98\xabN" + - "\xbeb\xb6\xdf\xc6Y\xddx\xa5B\xb2\x93\x10\xdf\xb2\xbd" + - ".\xdb\xb2\x04\xf6g\xbbe;E\xdd\xdc=b\x1a\xa5" + - "\x92\x92\xef\xf9\xc9\xa7{\x1c/J\x91\x07G\x88?\x9a" + - "\xf3\xc8\x1d\xc1\x13\x02\xe6\xc2\x85\x0b\x96\xebv\x8d\x1a%" + - "B\x08&\x90;\x16\xf3\x08!\x99\x9c\x9e\x1be\x01r" + - "\xf9\x14\x11\xff\xf5zI`X\xce|\xc3Z\xd7\xf0\xc2" + - "\x8b7\x92$m\xcb\xf4X\x9e3\xa1f\xb5\x04%\x1f" + - "0\x910\xcbs\x0c\x95t><\xb4f\x81>\xbc\x1f" + - "h\xdb\xd1@\x93uG&\xeb\xdab'\xb3\x89\xcc&" + - "\xdd,\xb3C\xf7?\xfe\xdb\xa5[\xbc,\x1do\xd4\xff" + - "J\xdb\x93w\xf5\xff\xf2\x01LK\xe8c94$H" + - "\xbc\xcb\xce\xb3\x81|8\xdb\xdc\x86\x19\xfd\x92}#\x98" + - "m\xee@\xfb\xeav\x90\xef\x8f(\xb3\xcd\xbdh\x8f\xdd" + - "\x03\xf2\x87#\xb2\xce4\xf5 \xca\x1f\x00\xf9c\x11\xa5" + - "\xf4\xebQ<\xcf\x01\x90?\x15\x91\xd5\xa6\xa9'\xd1>" + - "\x94\xb1\x91\xfa:>\xdb<\x8bv\xe63 \x7f%\"" + - "j\xd9a\xb6y\x19c\x1d26\x12li\xde\xc2\xf3" + - "\xbc\x09\xf2\xf7\x83\x8a\x0a\x98m\xdeC\xbbT\xa6\x8dN" + - "\x13\x0e#\xaa9j\xda\xe8t\xe1/\xaaN\x1b\x9dQ" + - "\xcf\xcd\xe7$\xca\xa5\x9f\x0a\xcc\xe7\xa6\x1a~\xaa\x99\x0d" + - "\xdc_T\xed\xa7\x8a7rs{\x11:8\x16\x82|" + - "9\xfa\xa9\xd2\xdc\xdcnEG\x8cL'M\xb6ps" + - "\xfbxt\xdcH|\xbffM\x04\xe6Q.\xd3LS" + - "\xc2\xc1\xd4\x8b\xd7\x95\xb8\x7f\xe9:n\x86\x0f\xe0u\xfb" + - "C\xbfV\xcbtn\x86o\xc6\xf3\xc8\xf4\xd3Y3\xb8" + - "\x83IG\xb9t`\xcdn\xe2\x0e&\x03\xe5\x12\x0fp" + - "\xceL\xee`\xda\x81!\x99\xd0\x81\xd5>\\v7\x8c" + - "\x8cH\xc3\x17\x7fvY\x84J\x8b\x1a\xab\xf1O\xd5\x1d" + - "\x12\xb7\xc0\x90\xad(\xd2\xef\xd7]\x12\xaf@\xf00u" + - "\xd7\x83\x91K\xa8C\xe3rL\x87\x08\xa4\xae\x97\xf5l" + - "\x87\xb2<\x1f\xdeS\xb4\xc1:UaJO\xdd\x82\xc2" + - "\xa9\xe0L\xb1\xda\xed\x1c\x96c\xc6\x18\xeb\xa1\x18\xd5\x00" + - "\x03;X_\x04\x09\x93G{\x02\x95\xa2\xb3=\xdd\x84" + - "}p\x065ry\x01\xf9\xd0x\x1fi\xb7]o\x92" + - "bp*\xc5\xd0x\x17\xd1&\xb7\xae!\\\xb33O" + - "b\xea\xf1\xb9 \xc1K\x09\x89\xe6tdG\x0d\x88j" + - "\x14\xf1H\xbe\xc7\xd2I\x1c6\x19\xf2}:\xeed\xf0" + - "al{\x8am\x91X\xafkK`4g\xc7\xd2." + - "\xdd4I\x1c\xad\xa9\x90#\xc1\xd9\xd1Z[\xdcVC" + - "\x9c\xd3\xad.\xdba\x83\x94\xb9\xcc\xc3\x1e\xaf.V9" + - "T]@\x9b\x98\xb6\xef\xfd\xe6\xfc\xbb\xff\xe6\x8a'\xee" + - "\xc4\xd9\xb0\xcb\xb6F\x8cBX\x08{\xa8b\xfb\xc5j" + - "\xb1\xbd\xd8'\xdc\xbfX\xa1\xa4\x08\xf6\x09\x0f.V*" + - "\xf0E\xc1H\xf2\x91A\x85\xa7\"\xd8'<>\xa8\x04" + - "+\x82b\xfb\xa7\xb7\xc8\xb8D\xdc\x1eq{\x03C9" + - "^\xd4\x0b\xbd\xe1.\xc1\x1eq\x07T\xcd\x80\x8c\x9b\x8c" + - "\x14\x10R\x15\xf6\x9eq\xf9\xc8\xc10\xb7w\xf6\xb1\xb1" + - "\xae\x11B\x0b2Zn\xbb\x18]\"Z\xd9=D\xdf" + - "\x86\x045\xa7m\xde\xa2\xc2\x10V\xc1\x154\xd7\xea\xc1" + - "\xe6Z=\xd8|\xc8\x1e\x14;\xadG\x16+\x18\x06\x01" + - "U\xc7\xa3\x8b\x95n\xad\x7f\x80\xf7\xe0\xe3m\x12\xd8\x80" + - "\x86^Ni_\xd13\xc3\xb0\xca\xb8J\x874\xa1\xfe" + - "8S\xf9QErS\xdb\x04\xeb\xd2\x8b\xcc\xd17\xe4" + - "\xed\"\x8b\x09\x10\x8f\x85Z\x94F\x84\xcf\xb0-\xf0\x19" + - ".Pk\x12\x0fC\x8e\x839\xa1\xd9\x1e\x0d\x99fC" + - "~\xe9\xd0\xd7V\x12_t\xb1[\xb5\x0b\xa8\x12K\x07\x06" + - "F\x06\xfe\x84J\xfc\x0dL\x15\xea\xd8\x811cG\x90" + - "\x10c\x90\xef\xe7\x8bc\xe2v\xb4UW\xd6\xe5\xde\xbb" + - "\xf3\xf7\xde\xfb~~_\x7f{\xfe\xf7\x0ay\xf8p\xae" + - "\x11b\xa8\x95\x93FK\x8b/\xf6\xb8\x18;\x18\xcf\xf1" + - "\xe7\x97W\xef\xbe~\xfa\x88\xbc\xd9!Z\xd3\xfc\x86\xeb" + - "3\xf0\xec\x03\xe5\xb4rsQ\xb1\xbe(S\xd7\xec\xac" + - "b}\xe1 \xe4\xdd\x9eC\x97\x0bY\xae\xe3\xfd\xba\xb0" + - "\xf8\x87\xa5\xf0Xi\x1c\xb1\xd0Y\xc7\xc9I\xc8i\x94" + - "\x9ab\x09\xdd\x8b)p\x0bo\xb2=\x9c\x1e%y\xc8" + - "Y\x1f\x12\x88h\x9c\x97\xc3\x84|\xc9Z\xc3\x8f\xec\x10" + - "*=D\xd4W\xef\xf0\x14+\x1c\x1b\xaa\xf9\x9bU\x04" + - "\x84\xfa\x0f\xb0\x834tF$S\x92\x94D\xfa{\xaf" + - "z\x90\xe7\xa6~\x99`[\xe9T\x91\xcc\x92e\x98\x90" + - ".P\xa4L\x0f\x90hX\xf9p\xf9\xf0\xa6}\xf9\xe3" + - "\xbb6\x9e\x13\x9d(MI\xe8>H\x11{\x1d\xb2\x91" + - "\x93\x0e\xc4\xfa\xb0!^\xcb\x93\xcc\xf3\xcd\x0eB\x06r" + - "\x81Z\x83\xc4?\x16\x18\x92\x86:\x88\x80\x8e\xa5F\x07" + - "\xa6\xeav\xddT]\xa8\x81P\x89\xe3\xe7\x1e\x98\x83:" + - "q\xcc\xba\xa0\xdcA\xaf\xbe\x0b\xe5\x0ez\xf5\xbd\xed\x80" + - "r\x87uM\xca\xea\x01X\x89:\x8b\xf2\xfetl\x1f" + - "F[\xecKu\xcevcN\xed\xf1)9&\xe9\xa8" + - "\xdcZbs\xef}\xbf\x88c\xca\x8d\xe1\x94/\xbe\xd4" + - "#s\xa9\x8e\xa9\xf4\x7fH3\xa2\xce:\x0d\xfc\xc2\x9f" + - "&\x84\xdb'V\xb7\xab\x88r\x08E\xa5p\xf3eD" + - "\xfe\x96\x12\x0eC0\xb6\xc1\x96\x9dl\x16\x91^a\x99" + - "\x17w[\x14\x0e\xa6\x94w\x19\x1b\x8e\x09\xc7\xc3\x10\xff" + - "7\x12vw\\\xda/\x8e*o\xc7\xeb\xd2\xe79H" + - "\x9f\x83IQFZ\x80\xdaB\xee\x02F\xafdL\x85" + - "\xa4%\xfc\xbc\xa7\xcb\x91\xb8\xde\xb0\xc7~\xa6{hA" + - "\x0b-\x90\x80$i\xfd\xf1\x13!\xc8l\xf6\x10rX" + - "\x1c\xb7X6\x8fX\x96\x0f3v\x02M 6\xee\x0b" + - "\xe9\x11w4\x85\x87F\xfb\xee\xe9DV\x06\x01\xe5\xba" + - "\x0c\x80\x17-\xfc\xf65\x18\x9b\xdd\xa70w\xa8\xa80" + - "\xb9c\x7fM\xd1h4^\x89\x9eZ\xa3\xbaI\xc2\xec" + - "I\xf7\xbf\x00\x00\x00\xff\xff^Ib\xec" +const schema_f3b1f17e25a4285b = "x\xda\xac\xbd\x0d|T\xd5\x99?~\x9e{'\x99$" + + "\x10&\xc3M\x0cP0B\xa1\x02\x15\xca\x8b4J\xa5" + + "1$A\x83\x89d2\x01\x85J\xeb\xcd\xccIra" + + "\xe6\xde\xe1\xde;\x09A-\xc2\x8a\x15*\xadX\xb0b" + + "a\x15\x17v\xd1\x95U\xac\xb8`\xb5\x15+\xadXi" + + "}\xa3\x8a\x95\xf5e\xb5\x8a\xad[q}\xaft\xfe\x9f" + + "\xe79\xf7m&\xc1\xee\xee\xff\xb7\xfb\xa9d\xbe\xe7\xdc" + + "s\xcf\xcbs\x9e\xb7\xf3\x9c\xe7N[r\xcd\x85\xa1\xe9" + + "\xe5\x0b\xfa\x98\x14O\x15\x15\x15\xe7\xae\xf8\xf5\xaf\x9a6" + + "\xff2~-\x8b\x9d\x09e\xb9\x83\xb1\x7f\x0b_\xd2\xbd" + + "\xf9?X\x11\x84\x19\x9b\xb9\xf1\x1b7\x83\xb2\xeb\x1b\xd5" + + "\x8c\xcd\xdc\xf3\x8d\xb3\x8b\x19\xe4\xba\xd6>\xf5\xe4\x9d\xdf" + + "*^\xc3b\x93\x01r]\xdf\xf9\xcd\xab\x8f?\xf8\x9b" + + "\x97X\x91\x84\xd5\x0f\xcf\xbd\x1f\x94\xd7\xe6\x86\x19S\x8e" + + "\xcf\xbd\x97A\xae\xaf\xa4i\xf7\xd4m\xe1\xb5,\xfa\x15" + + ")W\xba}\xd8egd\x9e\xbf\x971\x98\xb9\xa5\xe1" + + "~P\xf64`\xcd\xbb\x1a\xb0&\xdc\\\x7f\xf8\xca\x7f" + + "\xfc\xc1:\x16\xfb2\xc8\xb9\xfb\x12\xd9\xca\x0b\x87\xc2\xe7" + + "\xacJ\x0e\x03c3O5\x98\xc0@)m\xecc\x90" + + "[\xfa\xd9o\xffx\xf5\xf1\xe3\xebX\xac\x0a \xf7\xad" + + "\x89;'|\xf7\xe4\xde\xfffM\x10\xc6\xe6V4~" + + "\xa6\\\xd3\xd8\xc7\xd8\xcc\x93\x8d?\x04\x06\xb9\x09\x1b_" + + "~\xf8\xf8\xae\xb2\xebYt,\xe4N\xfc\xeb\xd7\xcb\x97" + + "\xd7\xadx\x9c\x15\x95b\x87\xb7\xcf\xbb\x1f\x94}\xf3\xf0" + + "\xcf\xbd\xf3rX\xfb\x1d\xed\xba\xcc\xb3\x1d\xb7]\xcfb" + + "\xe3@\xca}+\xa1\x8d\xfai\xc7\x8a\xdf9\xd3\xb1\xa9" + + "y\x15(\xbb\x9a\xf1\xcf\x1d\xcd5X\xfd_o\xf8v" + + "\xf3=\x07\x7fz=\x8bM\x80Pn\xc7\xa4\xa6\xe7\xb5" + + "\xdb\xee\xbf\x93U\x01u\xfb\xc0\xfc\xb5\xd8\xedC\xf3\xdf" + + "b\xf0\xca\xe2\xab[n\xb9m\xdd\xf7\xf2;M\xed*" + + "\xdb/yG\xb9\xeb\x12\xfck\xd7%o1\xc8=\xf8" + + "\xceg\x8d\x93\x8el\xf9\x1e\x8e0\xe4W\x0ea\x0d\xb5" + + "\xe5%%\xdd\x82]\xd0Z\xa8\x0b\x9f\xcf\xaa\xee\xf8\xcf" + + "\xcd\xcf\xad\xc7\xca\xc5\xf9\x95g\xf6\xb7\x96\x81\xb2\xbe\x15" + + "\xd7oSk\xad\xc4 \x17\xab\xfd\xd67?\xdds\xf9" + + "\x06\x16=K\xca\x9d\xb9\xf8\x8d\xec\x84\x7fL\xfe\x0b\xae" + + "\xc8\x9b\x0b\xdaA\xf9t\x01>\xf5\xe1\x82\x086\xfc\xef" + + "\x7f\xb9(\xf4\x81\xbeg\x03\x8b\xcd\x82p\xee\xba;\xc7" + + "\xcc/}\xe9\x82\xfd\xacJ\xa2\xb1mo\x93$\x063" + + "\xf7\xb6Q'n\xbf\xe7\xaa\xb7\x86\\\x92\xfc>\x8bV" + + "\x0d\x18\xdd\x9b\xb1\xf7\x95\x93\xb1j\xc6\x94Ocu\x0c" + + "r3\x1f\xdaP\xf3\xce[\xff\xf1}\x16\x1b\x0b\xc1\x15" + + "!\x12\x9a\xd4~?(\xf5\xed\xf8\xdc\x9cv\x9c\x0b\xf8" + + "" + + "\\\x97\x1b\xe6?\xa4\xac\x1c3i{\xe1\xbaP\xbb\xe5" + + "+\xcb@\x19\xb3\x12k\x8f\\\x89$\xf7\xf9\xfcG\xd7" + + "N\x89_\xb6]\xb0\x81?\xdd\xbcs\xf2\xbd\xfb^\xdc" + + "\xe9\x90\xf3\x81\x95\xcb@9\xb2\x92hj\xe5e8\x17" + + "%]\xbb\xfft\x9e\xb9t;\x8b\x9e)\xf9}\xc6=" + + "\xb7j>(\xd3Wa\xc3SV\xfd\x1a\xe5\xc3=#" + + "\xdf\xdd\xf9\xbb\xdf\xdd\x81+\x02\x05+\xb2u\xd5*P" + + "\xf6P\xe5\xbbV\xe1\xacu^0Ry\xe6\xe5\xa7\xef" + + "`\xd1\xf1\x81Ic03z\xd5ZP&\\\x855" + + "\xc7^\x85\xa3\xf3\x88\xb7`t2\xb6;\xe7\xaa%\xa0" + + "\xc4\xaeB2\xdas\xd5\x02\xdc~\xcd\x13V\xdd\x9c\xb9" + + "~\xea\x8e\x82\xb5\xa3\xe1)sV?\xab4\xaf\xc6\x07" + + "\x9bV\xd3J\x7fi\xf7g-\x93\x8f_\xbe\xa3\xa0q" + + "\xea\xf3\xb1k\xc7\x81r\xe2Zb\xa5\xd7\xe2\xccyb" + + "&\x9fs5A\xb8\x0c\x8ag\xae_3\x19\x94\xadk" + + "\xceF\xfa[C\x9cn\x94\xfc\xf1\x83g\xfe\xf1\xc5;" + + "i\xea\xce\xd3?l|v\xad\xfc\x17\x1c\xe3\x81\xeb\x96" + + "\x80r\xe4:\xa2\xa1\xebp\x0f\x9e\xbcv\xeb=7\xbc" + + "\xf3\xc6\x9d\xc8\xe5$\x7f\xe3P7N]w7(U" + + "\xebh\x8f\xad\x13\x92g\xfc\xe7_}d\xd2\xb9;Q" + + "\xf8\x05z%\xd6{\xd6\xf5\xab@i\xbe\x1e\xdbn\xba" + + "\x1eg\xfa\xd8\xf9;\x1f]\x7f\xc6\x91\x9dH\x9f\x90\xbb" + + "W\xba~\xf5\xfdg\xac=\xe8\xd4\xdez\xfd|P\xf6" + + "P\xed\xbb\xae\xc71z\xf4\x10\xab\x82H`\xfa\x86`" + + "\xed\xc5\xdf+\x03E\xfb^7c3\x0f}\xef\xde0" + + "\x83\xdc\x9b{\xf6\xd7\xfea\xc5\x1fw\xb2\xc1\xc4\xeb\xa1" + + "\x9b>S\x9e\xb9\x09\xff:r\x13\xf6d\xd8;\xfa\xfc" + + "\x92\xe3\xaf\xecb\xd1\x91\x90\xbb\xe5\xc1o\x8ex\xfd\x82" + + "\xbd\x9f \x07\xab\x00e\xca\xa6\xcf\x94\xf37a\xddY" + + "\x9b\xb0\xees?.o\xfc\xa8\xbd\xf2\x9f\x07\x13l\x9b" + + "6\xbd\xafl\xdf\x84\x82\xed\xaeM\xb8S\xa6\xfc\xe4\x86" + + "\xf7\xdf\x9b7\xfb\x9f\x07\x9b\xbd\xe3\x9b\xee\x06\xe5Cj" + + "\xf8\xe4&d\x05\x9e|\x8a\xd5\x80\xe4\xeb4\x82\x8f>" + + "s\xf3\x06PN\xdc\x8ckX\xf4#\"\x7fOT\xc7" + + "\xaa\xa0,\xd0\x11j<\xbdY\x02\xa5\x7f3R\xdf\xa1" + + "\xcda\x9c\x8f\xe7G\xff\xf3\xb3\xc7.\x9aq7I " + + "\x8f\xf73\x98\xb9o\xdb\x06P\x8el\xa3%\xdf\x86d" + + "\xad^m<\xba\xe5\xda\xed{\xb0\xd3\xa1\xc2No{" + + "\x12\x94O\xb7\x91N\xb0\x8d\xd4\xa3\xae\xca\xb9\x0f\x9d;" + + "\xbf\xfb\xdf\x0a\x99\x81Rt\xfb\xebJ\xf4vl\xb6\xfc" + + "v\\\xbf\xef~\xdc\xf1X\xc5\x8a\xc8\xbd\xd4\x01o1" + + "\x19\xcc\xec\xbf}\x15(\x1b\xa9\xe6\xfa\xdb\x91\xe6\x8a+" + + "{\xea\xae:o\xdd\xbd\x053\x8c\xdbJ9p\xfb;" + + "\xca\xa1\xdbk\x19SNP\xab\x9e\x0aY\xc0\x9b\x05\xff" + + "\xbcc\x06(\xfb\xee@\xaa\x18\xb3\x838\xff\xc4\xf4?" + + "\x9eT\x16\xed\xbf\x8f\xc5\xc6\xc0P\xffEb\xcb\xee\xf9" + + "\xa7\xc9\xa0<\xf2O\xc4m\xfe\xa9;\xc4 \xf7\xd4\x7f" + + "I\xafO\xde\xf6\xec^\x16\xfb*\x04\x84\x95\xc3A\xd7" + + "\xed\xbe\x1f9\xe8\x96\xddH\x16\x99\x19\xdd\xa3\xd6\\\xfb" + + "\xd7\xbd(\x05K\x02Z3M[\xd1]\xcb@\x19y" + + "\x17\xfeYu\xd7\xea\"\x06\xb9\xb36\x85\x9f\x8a\xff\xcb" + + "\xf4\xfbI\x0fN}o\xf8C\xdf\xfc\xd6\x90Wq6" + + "\x16\xdf\xfb\x0e(\xd9{Iq\xbdw5\x83\xdc\x81\x1f" + + "\x8f\xde\xf7\xed[\x9f\xbe\x9fE'I\xb9_\xc5\x87\x1d" + + "\xa8x`\xe4\xa7Xs\xd7\xbd\xf7\x83\xf2\x08\xd5<@" + + "5\x9b\xca^O\x8d\x9a\xff\xe7\x9f\x16\xee'\"\xa0\x0f" + + "\xef]\x06J\xe9}X\xbb\xe8>\x9c9\x8f\xb5\x0d\xc6" + + "\xbdv\xdd7\x0e\x94}\xf7]\x84J\xf3}\xd5\xc8\xbd" + + "\x9e\xfb\xb8lx\xf2\xb7\xdfyp0V\xaeL\x7f\xe0" + + "3e\xce\x03H\xf7\xcd\x0f )wm{\xbagW" + + "\x99\xfe \xf1P\xaf#\x0cfN\xdaw\x1b(\xf5\xfb" + + "\x88\xe3\xed\xabE\x9d\xc4U\"cU\x10\x0e4K}" + + "\xae\xdfw7(\x8b\xb1\xf6\xcc\x85\xfb>\xc6^l/" + + "Y\xae\xfe\xee\xafe\x07p\xfd<\x05\xda\xd1\xad\xf7\x1e" + + "\x98\x8b\xcbq\xe0\x00\xee\xbc\xe1}\xdf\x1c\xdf\xff\xfb\xe6" + + "\x03\x05\xdaYU1U=v\x00\xad\x87\x99o\x1e\xf8" + + "\xda\x10\x06\xbe\x8e\x15;\x0b\xc2\xbeD\x16\xfa\xf2\xaf\xe6" + + "\x83\xb2\xf1W\xf8\xe7\xfa_\xfd\x0b\x92\xd0\x1d?X\x7f" + + "\xf6;\xc9\x1b\x0f\x08-\xca#d\xaa=\xfd\xb0\x09J" + + "\xd3a\xd2@\x0f#U\xdcpu}\xe47{\x7fy" + + "\x00\x8d#9\xf7\xc8gW<\xf0\xd3e\xc9g\\\x02" + + "\xda~\xf8n\xec\xf1\x9e\xc3\xb8\x1eC\x7fp\xde\xad\xd1" + + "M\x87\x0e\xe0\xf6\x1f\xeeo\x7fjw\xe9\x93kAY" + + "\xf1$\xed\xec'i;\xdf\xdc\xaf\x0e}j\xe6\xbd\x0f" + + "a/Jsg\xee{{\xf2\x0f\xa6\x9fx\x8dU\x95" + + "R\xc3\x87\x9f\xe9\xc4\xf1\x1d}\xe6v\xa4\xe2\xf8\x0f{" + + "zs\x93\x93?\xc3\x96\x03\xc6\x92\xe0\xb3c_\x98\x0f" + + "\xca\xac\x17p\xed\xe6\xbc\x80]\xde\x1ez\xe6\xf2\xc3\xdb" + + "~\xfd\xb3\x01\xfb\xf4\xae\x17\x96\x81\xf2\xc8\x0bDo/" + + "`\x8f\xd7\xedy\xf4{m\x7fy\xeca!V\xbd\x9d" + + "H=\x8e\xbe(I\xca\x94\x17I\x9f|\x11+\x8f\xfe" + + "\xedK]\xef~\xfa\xe5_\xb0\xd8D\x00_m\x17\x0b" + + "}\xe8\xc5;A9N\xb5\x8fQ\xed\x8f?\xfc\xfa\x9b" + + "\xff\xf6\xec\xb4_\x08\x9d\xd2\x13\xeeUU4\xbcM\xc7" + + "\xe6\x93\x16|\x8c\x84\xcesO]v\xf0\x1f'\xecy" + + "\x94:\xec\xd9>8\xfc\x97f\x80\xf2\xe6K\xd8\xeak" + + "/\xa1\x1e\x90\xfb\x87\x19\xcf<\xd0\xf6\x87GYt\xaa" + + "\x94\xbb\xe2\xf9\xa1\x7f\x9a\xf2\xe3g?!\x16\xf4\x87\x97" + + "@\xd9\xf2\x07b\xe1\x7f\xc0\x9a\x1e\xcd\x0e\xc6V\xa2/" + + "\x8f\x03e\xec\xcb\xb89\x16\xbfL\xf24\xfe\xad\xd6\x7f" + + "\x9d\x18\xfd\xe6cd\x92\xec^rv\xe5\xde\xaf\xdfG" + + "&\xc9\xdeW>\x03\xe5\xc8+\xc4\\_\xc1=\xda\xfa" + + "@\xb1\xb9\xef\xce\x96\xc7\x0a\xb7\x11)\x01\xf0\xea\xfbJ" + + "\xf9\xab\xc8\xe3'\xbdJ\xcc\xf5G\x1b\xef\x0b\x8dxx" + + "\xebc\x03\xac\xe5\xc5\xaf\xdf\x09\xca\x8a\xd7\xf1\xa1\xf4\xeb" + + "\xc83\xbf2\xff\xb6\xd8\x7f\xec\xfe\xa7_\xe2\x1a\xcb\x85" + + "\xc2c\xfb\xebsA\xd9\x83\xb5g\xde\xf5:\xd9#\xd7" + + "\xfe[\xd1\xd1\x9a\x7f\xfb\xcd/\x0bX,\xd9\xcb\xfc\x8d" + + "\xf7\x95\x15o\x10\xad\xbdA\x95=i\x91oO\x16E" + + "I;\xfcc\x19(\xd9?\xa2y\xfd\xda\x1f\x89\xb5\xad" + + "\xb3\xcf\xdc\x137\x0e?\x8ek\x17\x10\x97D\x16\x0b\xdf" + + "\x9d\x0f\x8a\xf6.\xbd\xe6]\xa46\xcf\x16\x1aD\xa1=" + + "\xfcn\x19(\xc7\xdeE\xf5\xf7\xcdwI\x13o\xfa}" + + "\xd9\xad\xbfx\xfbG\x87\xd06\x92|\xad\xbf\xaa\x84\xc8" + + "b\xcd{h\x1c)\x9b\xdeC\x16\xf4\xef'?\xbc6" + + "\xbc\xff\xe3'P\x15\x91r7\xacZw\xee\x8f?\xd8" + + "\xff[\xc7~\xd9u\x92\xcc\xf0\xbd'\x91Ux\xb6M" + + "\xbe\x0aN\xb6\xf5\xd1\x93\xaf+\xaf\x9d$\xf7\xc5I\xec" + + "\xee\xb2\x0d\xef\x1f\xd9\xfb\x8d\x8f\x0f#[)\xf2\x9d\x12" + + "\x82.&\xbco\x82r\xfe\xfb\xa4\xeb\xbcOt\xb1o" + + "x\xeb\xf7*.:\xf3I\x16\xfdJ@\xef\x14,v" + + "\xcd\x87\xab@\xd9\xf2!\xd1\xdc\x87H\xf3C\x16\xfc\xf0" + + "\xf8\xfco\xdf\xf2$\xce\xdbp_\x82\xd0T\xf0\x8f\xda" + + "A\xe9\xff\x08\xff\xcc~DL\xab\xf5\xfc=]\x9b\xa5" + + "\xbb\x9f$\xb1\xe0\xcd\x04\x83\xdaC2\xac\x85\xeac2" + + "\xee\xee\xea\xa32 u<\xfb\xdc\xfd\x1f_rs\xed" + + "\x91B!][\x14\x82\xc9P]\x15\xa2\xca\xd1\x10U" + + "\xbe\xf5\xc7\xe3\xb5\xd5\x8f.{p\xf8\xa8\x17\xc8\x96\xf2v" + + "-\x83\xda\x0f/\xc4\x8dXZO\xcd\x17\xd5\x03\xee\xf1" + + "m\xbf_\x9ayko\xc5\x8b\xb4[{s\xd6\xf6" + + "p\x1b<\x09\x0c\xaa\x8f\xb7Q\xef=\xe7.qvO" + + "\x94\x09\xf2\xdc\x11C\xf2\xdc\x17\xa3\xedu0\x06\xc8\x84" + + "\xd5{\x9ey\xf6\x96\xef\xbf\xf9\x87B[\xba\xf6p;" + + "\xdc\x06\xd5\xaf\xb5\xd3p\x8f\xb7\x03\x8a\xc6/_i\xde" + + "\xb4^\x19\xff\xf2`\xccal\x1cFA\xf5\xf48\xd5" + + "\x9f\x12\xa7\xc6\x95o\x9e\xa5l\xb8q\xda\xf1BE\xa5" + + "\xf6T\x1c6@uU\x87`j\x1d\xd4\xf8\x99\xf3\x96" + + "\xff\xfb\xf9\xcb\xbf\xf2\x1f\x83\xf9pj\x9b;\xb0\xf5\xc5" + + "\xf4@\xed\xc2\x0e \xa9\xe7-\xe5\x80\x9dU\x04\xa1j" + + "X\x04\xefW\x97/\x82>\xc6j7.\x12\xfb\xc4S" + + "\xe3cU0\xa4@i\xa8=y\x19\xcc\x80j\xb8\x9c" + + "f?z9\x90R\xed\xed\xbe|\xf6&\xd6\xab\xff[" + + "\xf0\x0eTo\xf9\x16\x9c\xcdX\xed\x9eo\x89\xfd\xfe\xb7" + + "m\xfd\x9b\xb4q\xff\xf0*\xd2g\xb1O\x9fUQZ" + + "\xaf\x1dK\x01\x15\xbf\xea=Ki\x86\xdaRcf\xb7" + + "\x96\xbd\xff*\x8b}\x0d\x02\xc6\xb9\xd0\x97k\xb7~\x1b" + + "\x9e\xa5\xca\xdf&V\xe8\xe9\x90\xb1*(\x0d\xf4\x9e(" + + "\xff\xc8\xb7\xa1\x0c\xaa\x8f\x7f[\xd0\xce\xb7E\xef\xbf\xf6" + + "\xf2\xa4\xeco\xf7\x87\xff\x93\xc5\xbe\x81\xc2\xb0\xf7\x9e\xeb" + + "\xaf\xd9\xb1\xf3\x1dG\xb9\xad\xcdv\xc2\x0c\x89A\xf5\xc6" + + "Nj\xfe\xf5\xaa\xb3\x7f\xc0a\xfc\x1b\x05\x9c\x19GZ" + + "\xbd\xb7\x13\xde\xaf~\xa4\x93\xd6\xeb@'m\xda\xf2\x8d" + + "\x1f|\xfc\xf6\x05?y\x83\xb8\x88\xe7H`P;+" + + "\x81\\\xa45!\x16.\x01g\xe3\xac|\xe3\xed'\xbf" + + "4\x0c\xe0MA\x98y\xa2\xb3\xf6T\x02\xb7a4I" + + "\x0f\x94'\xe1;\xc5\xa8>\x9fQ:\xe4O7\x9d\xf1" + + "\xc7B\x95\x86*\x1dY\x0e&T\xbf\xb6\x9c~\x1c_" + + ".\x06\xbb\xe7\xbdW\xae0\xdf\xb6\xfe(^\xe1\xbb\xc8" + + "\x88\xf6W\x18\xb8\xb5\xd6\x184\x82k\x0c\x9a|\xafJ" + + "\x81h\xa9\xc2:j\x06\xde\xafNg\xa0\x96\xb1\xda\xed" + + "\x19 5}\xfd\xb97\xfe\xc0~p\xdc[,6\x0d" + + "\x86\xfb\xe6\x00i,\xb5\xebz\xe1%\\\xac\xad\xbd4" + + "=;\xd7\x7f\xf4\x9b\xb6;\xec\xb7P\x0f)\xce\xb7\xd1" + + "k?\xec\x85\xfb\xa1\xba\xbc\x8f\xba_\xda\x07\xa4\x89<" + + "\xb2\xfd\xa7\xfb\xe7\x95\x0fy\xbb\x90\xfe\x89\xd2F\xaeB" + + "F8e\x15=1i\x95\xa0\xff\x13\xff\x90*\xbfm" + + "\xed\x99o\x0f\xe0k\xfb\xae\xc2\xedu\xe4*\x1a\xec\xe1" + + "\xab\x04\x1f\xff\xc7\x17~+\xfdv\xfb\xdbB1\xf3\x0c" + + "\x0e\xea\xcf\xd2\xab\xb1~\xf6jj}\xc5\xd5\xa2\xf5\xfb" + + "\xb7\xde/\xed\xfe\xe9_\xdeF)\x14p\xd4\xd3\x03\xe5" + + "\xdf\x85N\xa9z\xfaw\xc5f\xff.\xcd\xa6\xa7<\x15" + + "\xcc&=0f5\xee\xad)\xabi:\x17\xaf\x16;" + + "\xc5\x13=\xb1*()\\\xe2\xe9kP\xd9\xa8_C" + + "\xf4\xdc\xba\x06\xc8A\x97\xfc\xce\xad\xfa\xf6\x03\xdf?1" + + "\x80[\x9d\xba\x0e\x09\"\xba\x8e:T\xbe\x0e\x99\xf3\xa9" + + "C\xbf\x9c\xfe\\\xdd\x81\x13\xb1I0\xceg\xd4\xe2$" + + "\xa4v\xfa:@M\xb4\xba~\x1d\x92\xfe+S\x1e\xfc" + + "\xe3\x81'\xfex\xa2\xb0Uu\x1d\xceK?\xb5Z\x9b" + + "]\x07t\xc4\xe2\xc9\x84X\x15\x0c-\xd0\xcc\xab\xa7\\" + + "\x0f\x9fU\x9f\x7f=u\xba\xe9z \x8b\x98\x7f\xe9\xdf" + + "\x97\xddr\xeeO\xdea\xb1Q\x10\xf01V\x15QO" + + "\xf6l\x80\xc9\xd8\x93}\x1b\x88l\xbc=\x1a\xfb\x0a\x14" + + "\xf9\x06\x85 \xe2\x91\xdf\x87\x97\xa0z\xd6\xf7\xc5\x04}" + + "_Hs\xcf\x98\xc9wJ\xd1\xb4o\xd9\x88T\xbfk" + + "#1\xa8\xc3\x1b\x05\x13\xf4,\xbb\x02\x87v\x84^\xf1" + + "C|b\xd2\x0f\xe9\x89\xfa\x1f\xc2_\xd0^\x9865" + + "\xb3\xf9\xb1\x93\xc3\xdf\x1d\xc4\x04\xa8-\xbd\x05\xa5\xdc\x98" + + "[h\xe6G\xdeB\x9c\xa4\xf1\xb3\x05o\xa89\xf3\xbf" + + "P\x1d)\xf3\x15\xd4\xaa\x10\x8d\xb8\xfe\x16\xa1\x8e\xb4\xde" + + "\x02dB\xdd|\xf0\xcd\xc3/\x1e\xd8\xf5_\x85\xae\x88" + + "\xda\xec\xad\xb8\xa8\xebo\xa5\xa6\xd7\xdd\x0a?f\xe0\xbb" + + "B\x07v\xa5\xfa\xe8\xad\xf0~\xf5k\xb7\x92x{\xf7" + + "V\x9a\xce\xf5{\xbe\xfb\xdd3?\x1f\xf6\x17\xe1\xde\xf3" + + "\xe4\x97\xd8\xb1\xcd[\xc1\xc4\xa9_\xb8\x95z\xbd\xad\xe9" + + "\x177\xbe\xb2\xe6\xfb\xef\xb1\xd8\x0c\x18\xea\x9f\xb1\x0ar" + + "\\\xb3\x15\xee\x86\xea\xad[\xe9\xc7\x96\xadP\x87&\xfe" + + "\xd9\xe7\xfc\xec\xad%\x8b\x87\x9eD~P\x92\xbb\xf9\xfa" + + "\xab\x96\xbf\xf8\xc2\xb5\x1f:O\x14\xdd\x89\x02t\xcc\x9d" + + "\xf4c\xe4\x9d\xf0\xef8\x93\xdf{\xf5\x9c_\x1czb" + + "\xfdI\x16\x1b\x03E\xbew\x8bf\xf2\xf0n\xdc#\xc7" + + "v\xd3\x03Gw\x8b=2\xf6\xec\xd5/.\x99^\xff" + + ">\xd2\xc3\x10_~9\xd2\x7f\xeb\xdd\xb0\x01\xa7\xf2\xae" + + "\xbb\xc5B\xfdg\xf6G\xaf\x1e^z\xe3\xfb\xc2\xf8\xc9" + + "g:\x8b\xf7b\x7fV\xec\xa5\xe6\xd3{\x05\xf1,\xe9" + + "?\xf3\xa7\xc7W\xec|\x1f\x85U\xc4\x17\xd1UC\xa8" + + "\xf9C?%aU\xfb\xccO\xe1k\xc8\xff~\xb6\xe7" + + "p\xd9\xf7\x87\x9cz\x7f\x80\xdd\xa1\xedG\xb5\xeb\x9a\xfd" + + "\xb4R\xfd\xfbIO\xbbr\xff/v\xffq\xf9\xc4\xff" + + "\xc6\x9e\xcb\xf9\xbe\x87\xda-\xfb\x91\x01\xee\xd9/T\xa3" + + "\xfd\x82.??\xaa\x7f\x7f\xe8w\xbe\xf3\xdf\x83Y\x12" + + "\x9f\x1e\x802\xa9z\xe4C\xc2\x92x\x88t\x9d\x89W" + + "\x9cx\xe6\xf1\xff\xba\xfd\xbfYl\"\x84}\xc5\xca\xd9" + + "\xe1\x07\x1f\x82\xdbpq\x9fy\x88\x08\xc1[\x9c\xd8\x99" + + "\x10*82\xaf\x9d\xfe3\x14@M?\x13\xbc\xe6g" + + "Bk\\t}\xf7\x98\x87>Z\xf7\xe1 \xe2\xb0\xb6" + + "\xf4\xe7\xa8\xfbV\xfd\\\xe8/?\xa77\xfcb\xcd\xa3" + + "o?\xf3\xcd\xdb>\x1a09\xd9\x9f\x13\x19\x8b\xca\xeb" + + "~N\x93\xf3\xd1\xd6\x7f\xbee\xe6O\xfe\xf3\xa3B\xb7" + + "A\xed\xf6\x9f\xe3\xcc\xec\x13\x95\xf7\xfe\x9c\xb4L\xcf\xdd" + + "]h2U@\xf5\xf1\x9f\xc3\x93\xd5'~N4\x7f" + + "\xf2\xe7P\xc7Xu\xeb/\xa0\xda\xf7\x9d\xc4\xce\x82\x12" + + "\xbf;4\x99\xcd\xbf\xc0\x0e-\xfd\x05\x0dW\xfb\x05\x90" + + "O\xc0\xf3[\x0e\xc2F6\x1d\xc2=\xbe\xeb\x10=\xb0" + + "\xf7\x90\x90\x0f_}\xf1\xa9\x99\xdf\x9b}\xf8S1\xa3" + + "\x9e\xaaI\x0f4\xfd\x1a\xc5\xd5\xe2_\x0bu\xed\xd7\xe2" + + "\x81[F=\x7f\xfb\xf2I\xb7}6\xd8\x11`\xed\xf1" + + "'`\x1cT\xbf\xfb\x84P\xdc\x9f\x10\xd4\xb9\xe0\x86\xee" + + "\xa9\x99G\xbf\xf9\xd7\x820\x00z\xc5\x91\xdf\xe0n9" + + "\xfe\x1ba\xbc\xfe\x86D\xd0\x83w_\x19\xfb\xfdy\xfb" + + "\xff\xcab\xd3!\xe0\xad\x17\xc6\xebS I\xd5\xe5G" + + "\xa8~\xe9\x11\xc1l]\xef@\x81\xc8%f\x9b>\x82" + + "*\xe75Gh\xd0\xeb\x8f\x88\xedx\xf0\xec\xf3\xbf}" + + "\xdfO\x86~^xfAJ\xd2\xe2\xdf\xc1\xeb\xd5\xfc" + + "w\xf4\x06\xf5wD\xa3\x13\x96\x0e\xd9\xd6wp\xf1\xe7" + + "\x85G\xa9\xb5\xe5O\xa3i<\xe9i\xaa<\xe1i\xa8" + + "e\x90{\xbe\xee\xfb\xefm\xfeN\xe9)d\x0e%\x05" + + "\xcca\xca\xd3\xa8\xde\xcd\xa1\xfa\xb5\xe7?-z\xf3\xab" + + "\xb1\x99ou_\xfd\xe4)\x9a\x1fO;\x14$Z\xf4" + + ",.\xc1\xc8g\xc5\x8ey\x96\xc6\xdb\xf6\x93\x8dol" + + "_v\xee\xdf\xf2\x09\x89\xda\xdf\xf1,\x9a\xde{\xb1\xba" + + "\x9c\xfb\xdd;\x9f\x19\xeb\xf7\xcc\xfa\xdb`Lv\xe3\xb3" + + "\xf0N\xf5V\xd1\xec\x16\xd1\xecb\xfe\xc6\xf8\xbbb\xdf" + + "\xf8[\xa1o\xad\xf6\xd3gQ^U='\xb6\xc9s" + + "D\xf9\xd9\xe3\xdc\xfc\xcd\x07\xff\xf47\xa1Vx\xea5" + + "ub\xd2s\xb0L\xaan\x15\xf5\x9b\x9f\x83{Y." + + "\xf0\xff\x9bs\x09nr5\xf5\xb5T\x91\xd1\xfd\xb5\x94" + + "\xd1=5\xa1f\xf4\xcc\xecX\xc2H_\xa4[\xd6\xd4" + + "F\xb3\x95\xabV\xd6\xe4i\xae\xdb\xed\x11" + + "\xf1\xb0TI\xde\xfb\x09\xb2\xc9X|<\xe2\xd3\x10/" + + ")\xae\x84\x12\xc6\x94)\xd4\xfe9\x88\x9f\x87xi\xb8" + + "\x12J\x19Sf\xc9\xcf2\x16\xbf\x00\xf1\x8b\x11/+" + + "\xae\x842\xc6f6\xc9e\xc0X\xbc\x0d\x0b\xae\xc0\x82" + + "!\xe1J\x18\xc2\xd8\xcc\xc5r'\x16\xf4`\x81\x8d\x05" + + "C+*a(c\xca\x0ay.c\xf1\x14\xe2+\x11" + + "//\xad\x84r\xc6\x94\xac\xbc\x96\xb1\xb8\x8d\xf8\xb5\x88" + + "\x0f+\xab\x84a\x8c)\xd7PO\xafF\xfc\x06\xc4#" + + "C*!\xc2\x98\xb2\x8ezt#\xe2\xb7\"^1\xae" + + "\x12*\x18S\xb6\xd0\x086#~\x07\xe2\xd1/WB" + + "\x941e\xbb|\x1bc\xf1;\x10\xbf\x07\xf1\xe1\xd3*" + + "a8c\xca]4C\xbb\x11\x7f\x00qed%(" + + "\x8c){\xe5%\x8c\xc5\xefC\xfca\xc4+\xcb+\xa1" + + "\x921\xe5\x80|'c\xf1\x87\x11\x7f\x02\xf1\xaaa\x95" + + "P\xc5\x98r\x88\xfa\xff8\xe2O#~F\xa4\x12\xce" + + "`L9\"\xbf\xceX\xfcy\xc4_E\xbc\xba\xa2\x12" + + "\x19\x80r\x9c\xfa\xf3*\xe2\x7fF|D\xb4\x12F0" + + "\xa6\x9c\xa0q\xbd\x87\xf8\xe7\x88\x8f\x9c^\x09#\x19S" + + ">\xa5\xf6?A<\x14\x92 :j|%\x8cB\x82" + + "\x0b\x11\xc1!^\x12\x92\x00\xbeT\x09_Bz\x0b\x8d" + + "b\xac=\x84t\x12\x92\xa0\xce\xe4\xaae\xe8P\xcc$" + + "(fPg\xf1\x15\x97f\xd3\xc1\x9f\xad\xeaJ\xef\xa7" + + "\xd9\xd5bX\x16\x84\x99\x04\xa8\x94X\xfd\x96\xcd\xd3\xed" + + "6\xabK,RSZ\x12\x80I\x00\x0c\xea\xba\x1a\x8c" + + "\xacnC\x09\x93\xa0\x84A.\x912\x12\xcb\xdb\xb9\xc5" + + "\xc2\xdc\xb6<\xd4{\xba&\xd1\xa1\xa59\x942\x09J" + + "\x19\xe4\xba3V\x0bW3qV\xc7\x13\x86\x9e\xb4\xdc" + + "\xb7{\x05\x92\xc0\x17\xea\x09n\xda\xaa\xa6\xdb\xd0\x1f\xac" + + "\xd3a\\\x942d]\xb5,lv\xae\xa6Z\xadZ" + + "*\xa5Y\xe2)\xc6\xa0\x8cIP\x16\xa8\x1b:]]" + + "\xf7\x0da\xdd\xeew\x9fZ\xdd\x9d\xb1.\xe3|\xb97" + + "\x09\xdd\x19\xf1\x0c\xb8/\xf0\x06\x88\xedc\xab\xac\x06\xdb" + + "\xb5\x82x\x03\xce\x88\x84\xa5\xfe(\xfa[a`\x1dV" + + "\x177\xb2f\x82\xfb\x03L\x19\xd8\xdd\x06\xc0R,\x93" + + "\x07\x16.fa\xae\x9a\x85h#\x93\xd5~\xbf\xdb\x02" + + "l\x05w\xbca\x9cj\xef\xf5\xa2\xb4\x03\x9cY\x09L" + + "\x9a\xf3~\x09\xdf\x1f\x1c@p\x92\xc4\x8a\xcf39\xac" + + "\xc8r=\xd1?W\x93Uk@\xa1$\x0a\xf3\xd6\xd1" + + "\xad\xd3er*\x85~1~\xe6\x93\xa4\x98\x8f\x88\xef" + + "kc\x00\x11\x06\xb2\xd5\x0b\xc3\x18\xb4\xc9\x00\x15>\x1b" + + "f\x80\xe0i\xd8y\x8b\xd6\xcb\xdb\x0c\x8bO\x9d\xa7\xa5" + + "ln\xc6m\xd5\xe6S\x17tZ\xdc\xec\xadQm\xcd" + + "\xd0\xdb\x00bC]\x0e\x1em\x9a\xccX\xecB\x19b" + + "-\x128\xdc;\xda<\x83\xb1X\xa3\x0c\xb1+\x91w" + + "\x03\xf1\xee\xe8R\x04/\x97!fK\x10Y\xae\xe9I" + + "\x081\x09B\x0cjz\xd5T\x96\xbb\xdd\xc4\xb1\x0ec" + + "P\xc3M\xd30\x0b\xc0\xd3\xf4\x18\x85O@\xf2XS" + + "\x1b\x0c\xdd\xb2y*\xa5\xda5\x9a\xa17'\xb1\xc7\xa3" + + "\xa9\x13\xad\xe3p\xf0\xd4i\x90\xa2s\xe62\x06rt" + + "\xd6l\xc6 \x14\x9d\x82`Qt\xc2\x0c\xc6\xa08:" + + "f.c\xe1\xee\x8c\x15\xb1:Uku\xb7\x9a\xd2R" + + "\xdc\xa8\xeb\xe4Z\xd2\xc8F\xb44\xb7jV\xac\xd2-" + + "k\xb5\xb3\xf4^\xd7By]k4\xb5^g\x0e\x17" + + "\xcd\x98\x9a\xe4\x19\x93\xd7$T\x9b'c%r\xa8B" + + "H\xb5\xe8\xa4\x0d\x8c\xc5\xce\x91!v\x1eJ@\x99D" + + "Wt\xd6*\xc6b\xe7\xca\x10\xbbP\x82\\\xd2\xca4" + + "\xad\xe4\x89,\xe0\xfc#}\x056l\xc60\xccE\x9a" + + "\xa5\xb1:Co3\x8dN\x9f\xa2\x9c\x1eIy=Z" + + "\xd8\x99\xaa3V\xe2\x94\xc5FC\xe0\xe43:\xbd\xdd" + + "\xd7\xd8\xa2\xd3o\xf6M\xf6\xe8\xacv\xff\xf0,:k" + + "\xbe\xafb\xe0\x0fOo\xc5j\x9eK&:kC." + + "\xae\x0a%\x80\x81\x9ds\x97\x07|\xcd \xd7\x94\xe9\xe1" + + "inj\x0c\xac\\\xb3\xa1\x1b\x8d\xaa\xad2\xc6r\x17" + + "\xf7\xe1|e\xad\xbc\xbfaF\xee\"1\xd3M\xe0<" + + "g1\x16\x1b-\x87\x86\xe6rD\x88\xfbnf,\xb6" + + "_\x86\xd8\xe3\x12\x94\xc3\xdfr\x82\x14\x0f\xb63\x16{" + + "T\x86\xd8S\x12\x94K\xa7rb\xc6\x0f\xcfg,\xf6" + + "\x84\x0c\xb1\xe7%(\x97?\xcf\x91\x16\x11}\x06\xd1\xa7" + + "e\x88\xbd,Ay\xe8\xaf9\xb1\x10\xc7\xb0\x85\x17e" + + "\x88\xbd!Ay\xd1g9\xd2 \xa2\xaf\xe1\x9a\xbd!" + + "C\xec=\x09\xca\x8b?\xcd\x91\xfe\x10}\x17\xeb\xfeY" + + "\x86\xd8'\x12\xe4\xd2\x03\xc7\x0c\x15\xfe\x1c3\x80\x0a\x06" + + "9\xee\xcf\x02T\xf8\x93\xee\x94j\xfe\xbc@\x85\xbf\x0a" + + "Ni\x8f?SP\x11\xd4\xfc\xf2Ka\x06T\x04\xe3" + + "\"\xa8\xb4{\xe0lB\x85\xbf\x80N-\xcb_C\xa8" + + "\xf0\x89\xc5)\x1d|;\xb6\x1aI\x9e\xc2N/\x9a1" + + "\xb5Q\xb3\xb8\xde\xadv\xf36\x93'\xb5D\x0d\xd2\xaf" + + "\x85\xdbq\xbc\xc7@\xde\x1d\xceX\xecm\x94\xd3\x10P" + + "\x00\x01Po\x08\x01jh\x10\xd0\x00\xc7\xc0\xcd\x8c\xc5" + + "\xcfB\xfc\x02\xc4eYh\x80\xe7\x03\xea\x07\x17 ~" + + "9\xe2\xa1\x10\xad\xde\xcc\x850\x1c\x15\xab+\xb1\xe0j" + + ",(*\xa2\x05\x9c\xd9/\x0a\xae\xc3\x82;\xb0\xa0\xb8" + + "\x98\xd6p\xe6vQ\xb0\x1b\x0b\x1e\xc7\x82pX(\x81" + + "\x07\x01U\xabG\x11\x7f\x19\xf1\x92\x12\xa1\x04\x1e\x03T" + + "5^D\xfc\x03\x90\x00\xecB\xae\xd5i\xaa\xcby\xa3" + + "f\x81;\x15a\xa3\xd3*\xac\xd4\xadZ4Y \xaa" + + "\x18\x9d0\xa0\x8aesn.\xe8\xe5`\x9aZ\x12\xeb" + + "\xc8\x03\x9b\xa1w\xcdl\xe5\xb2\xcdM\xab\x8d\x9bq\x92" + + "\xbf\xf1\x15Y\xd5\xe4\xc9\xc1\x9b\xa5G\xce\xfd\xdf?2" + + "\xeb\x7f\xf5H\xb7j\xb5\x99\xdc\xb2X\x0d\x96\x0f\xdeb" + + "\x9b\xc9\xc1\xb2\xa8\x9c\x9d\x8e\xf5\xe7\xf3\xd7VUW\xbb" + + "]!\xd5f\x1a\x09n\xd5Y\xf4\x0b\x89\xac\xd2#\xb2" + + "kPJ\xad\x94!v\x9d/\xa5\xd6\x8cc,v\xb5" + + "\x0c\xb1\x1b\x90\xbe\xce\x12\x9ca\xdd\\\xc6b\xd7\xca\x10" + + "\xbb\x11\x89H\x98\x17\xd1\xf5\xc8\x18n\x90!\xb6\x19)" + + "n\xac\xe0\x0b\x9b\xd62\x16\xbbI\x86\xd86\x09\"\xba" + + "\x9a\xe60\x94I0\x94A8\xa3y\xb2m\xb5\x99\xd5" + + "uM\xefv\x95\xc0\x1c_\xa9\xd9\x0dF\x92\xe3\x96u" + + "\xea\xe4\xac\x1e#\x9bJ\xce\xe5\xd0.*3\xaf\xf6\xe0" + + "\x1b,\xceu\xcb0\x9bz\xb9n\xe36\x13b\x85\xa4" + + "\x0a\x8bUxCVq$W\xc8\x10\xeb\xf1\xb7U\x94" + + "\xcff,v\xa5\x0c\xb1\x94\xbf\xa7\xa2\x1aNNR\x86" + + "X\x06\x87\xf7(\x99*\xd1\xf42\xc6b)\x19b+" + + "%X\xdd\xcbMK3t\xb7\xc7u\x16\xf5\xc0\xfd\x19" + + "\xb1\xfb3\xdc\x1bMVO\xa8)\xad\xd3d\x11\xec\xd1" + + "\x80\xa1\xe4K\xa3\x06U\x8f\xe0\x18p\xb5\x06\xef:\xc8" + + "\x10\x08j\x8a\xf2%\xd8\x9e\xe8w\x0c\x17\xb0E\x86\xd8" + + "\xe58\x98b\xb1V\x0b\x11l\x93!v\x85\x04\xab\xd5" + + "d\x12i\xce\xd3\xe0\xdc\x99b2O\x86\x93\xaa\x0d\xe5" + + "L\x82r\x06a\xcbLx\x9a\xe1\xe0=\xed0\xb2r" + + "\xa2\xa7\x80\xaa\xc6\xf9T\xe5M\xf1\x9a\xc9A\xb2\xaap" + + "\xc8jr\x80\xac\xe4\"\x87\xac\x10\xbcN\x86\xd8MH" + + "k\xc5\x82\xac6\xce\xf0i-l\xf1\x04\x141\x09\x8a" + + "\x18D\xb2\xc1\x1f4\xe3N\x87#\x09#\xc9\x0b\x94)" + + "w1\xdc\xb1\xc8yci\xd2\xf1\x91f=\xc9W2" + + "F\x16\xba\x1f!\x04\x93#\x1d\xfd\x19\x1e\x9b\xe8\xd9\xe8" + + "\xa50\xd7e\xc5\x15\xc4\xa2%\xc1\xa2\xcba2\x1a\xdd" + + "\x88W\x06Yt\x14\xe6\xa3\xd1\x8d\xf8\xe8 \x8b\x1e\x09" + + "h\"\x8e@||\x80E+c\xa1\xdde\xe9\xe7\x04" + + "8\xb42\x89\xf8\xeaD\xc4\xcf\x85\x80\x91>\x1d\x961" + + "\x16\x9f\xe6\x89\x80pH\xf0\xe7\xf3\x09?\x0f\xf1F\xe2" + + "\xcfe\x82?\xd7\xc3\x0cW4\\\x8cx\xe9\x10a\xa4" + + "7\xc18\xc6\xe2\x17\"\xde\x02\x12\xac\xee2\xd54o" + + "N\xba\xc4\"\xe68\xe2O\x8d\xd0\xa8s\\L^\x12" + + "w\xb0g\xb5\xf1n\xd4\x91h\xafB\xd0\xde\x04\xd2\x1e\xc6#>" + + "\x8dh\xafT\xd0\xde\x14\xaa\x7f\x0e\xe2\xe7\x11\xed\x95\x09" + + "\xda\x9bE\xf8\xb9\x88_H\xb4\x17\x15\xb47\x87\xb4\x13" + + "_{(\x19\"h\xaf\x89h\xbe\x11\xf16\xa2\xbd\xa1" + + "\x82\xf6Z\x09oq\x0d\xd1\x1a\x9b\xa73\x0d\xded\xa6" + + "y\xda0\xfb;8\x0b\x07\xd1\x8c\xd1\xc7\xcdFSe" + + "r\xdfe\xf9`\x8b\x96fa\xcd\xbe,\xe0\x9e\xcd." + + "\xb4\xd4n\x0em\xdcLp\xddf\x01'oV8G" + + "\xc3\xad=\xab<\x8ff\x97\xaa\xc73\x9c'Y\xb8=" + + "\x93\xf6\xd0LB\xe3-\xb6e1\xf0\xbc\xda9+\x9b" + + "\xc9\xa4\xfa\x17\x19\xac&e\xe3\x0b<\x7f6\xe1\x0dY" + + "Vc\x9a\\\xb7Af\x12\xc8\xa7e\xf5\x0d\x86n\x9b" + + "FJ\xd8`SS\xaa\xcdM5%\xc0\xba\x94\x909" + + "\xa3\xe5\xd0\x98\xe2\\\xae\xa8\x12\xcee,\xba\xefN\xdf" + + "m3\xfao\x88\xceb,zp\xbe\xef\xb6\x19St" + + "\x0a\xe1Z\xc6\xa2\x87oc,\xf6\x94\x0c\xb1\x17%\x18" + + "\x03\x9f#<\x9b\xb1\xe8Q\x94\xd8\xcf\xcb\x10{U\x82" + + "1\xd2_\x11\xfe\x06c\xd1\xe3\x08\xbf,C\xecm\x09" + + "\xc6\xc8\x9f!|\x01c\xd17;}\xd7\xcd\x98\xd0\xa7" + + "\x08\xd73\x16}wU\xc0w\xa3\xe9I\x0d{\x0b\xae" + + "\x0e\x11\xeehj\x84\x8a\xdc\xb7kg\\\x7fnb\xf3" + + "\x8f\xbc\x1d\xae%iP\xc2\x03\xe3\x1d\xff;\xa5\xa9\x15" + + "\xc22\x05W\x11\x91\xa9\x91\xff\x98\xfc\xc4M/\xbc>" + + "\xfe&\xb7\x9a\xaaw\xa7x\xdcV\x99ls\xa8\xf0/" + + "\x949\xc5I\xde\x99\xed\xf6\x8b\xbd\x1bSN\xb1m\x98" + + "+\xb2F\xd9B\xff\x9e\xa9l\xa2\xf7\xd5(\x1b\xe9" + + "\xdf\xb3\x94\xf5\xd4\xef\xb1\xca\xfa\xd0K\x8c\xc18e#" + + "\xf5\xe3\xcb\xca\xfa\xd0\xcd\x8c\xc1x\xe7\xdf\x09\xce\xbf_" + + "Q\xd6S\xff\xcfv\xfe\x9d\xe8\xfc;IY\x1fZ\xcb" + + "\x18t*\xeb\xa8\xbd\xc9\xca:z\xffW\x955\xf4\xdc" + + "9\xca\x1az\xff\x14\xe5\x1a\xea\xefT\xe5\x1az\xff\xd7" + + "\x94~z_B\xc9\x86^g\x0c\xa6)\xfdT\x7f\xba" + + "\xd2O\xe3\x9c\xa1\xf4S;3\x95,=\x7f\xae\xb2\x82" + + "\xe6\xa3VI\x87Pi?O\xe1\xf4\xde\xf3\x15\x95\xea" + + "\xcfVT\x9a\xe7o(K\xa9\x9d\x0b\x94\xa5\xf4\xbe9" + + "\xcaRz\xee\x9b\xca\xe2\x10\x9a\x05uJ\x8c\xea]\xa8" + + "\xb4Ry\xbd\xd2J\xf5\xe7*\xad\xd4\xaf\x06\xa5\x99\xda" + + "oT\xea\xa9\x7fM\xca\x1c\xaa7O\x99\x13B\xd3\xe1" + + "\"e\x16\xbd\xf7be:\xd5O*SB\x8f1\x06" + + "\xcd\xca\x14\xaa?_\x99D\xed]\xa2L\xa2z-\xca" + + "\x04\xfa\xdd\xaaL\xa0\xf5\xbdT\x19K\xeb\xc9\x95\xb1\xd4" + + "\xef\x05\xcaXz\xaeM\x19C\xed\xc5\x94\x91T\xbf]" + + "\x19I\xbf;\x94**_\xa8D\xe9\xb9EJ\x94\xde" + + "w\x99\xf3\xef\xe5\x0e\xbe\xd8\xf9w\x89\x83\x7fK\x89\xd2" + + "\xbc]\xa1\x94\xd3{\x96*\xe54\xae/)E\xb4N" + + "\x11\xa5\x88\xda\xfd\xb6\x024\x1f\xdfQN\xc9X\xafK" + + "9%\xe3\xf3\xb3\x94S2>\xffuq\xf6\x08W*" + + "\x1f\xd2\xbf\xdd\xcaI*W\x95\x932>\x1fW\xde\x95" + + ";\x19\xcb%T\xbd\xc94\x0d\x13\x8d\x1d\xf2\xec-\xd4" + + "U\xe8U\xb5\x94\xda\x99\xe2\x8c\xe5\xfaLC\xef\xbe\x88" + + "\xab\x0c\xcc\\\xd20\xcc\x05\x19\xaeS]\xae\xda\x9d<" + + "e\xc3\xa5\x86\xdd\xa2\xda\x89\x1e\x99's\xdc\xca4j" + + "\x96\xda\xc9\xc2)\x9e\x14\x8f6\xa8&\x8b\xa0\xe6-Z" + + "\xef\xe0i\xc8,\xd4U|C\x04_\x913y/7" + + "-~\x11\x9d\x8b\xe5:\xb3\xb6m\xe8\x0d*\x8b\xe8\x09" + + "\x9er~6\xe9L\xd4%;\xad\xcd\xe4,bY<" + + "\x99\xcb\x98\xbcIW;S\x80,EOZvXK" + + "\xa5<\x17\x1f\xf0\xe4\x82^n\x9a\x9a\xec\xbe|A/" + + "G\xf1\xa1%y.af5\x8b7j\xac\xce\xc2\x96" + + "\x939\x0b\xc5S\x87a\xb0p\x8b\xd1\x973\xb2\xf6\x82" + + "\xaexFer\x82\xe7\x8c^n\xf6p\xd5f4]" + + "\xa8(\xab6h\x86\xde\xac'\x8ctM&\xc5m^" + + "\x80\xf7\xaa)\x19Uh\x07\x944Co\xe7\xee/T" + + "\xd6X.\xe1H(h\xd5\xac4\xce\x1fc\xb9L\"" + + "M\xe3a\xc0\xf1o1\x952\xce\x91\x9aT\xcdyj" + + "\x96\xc9)[\xf8(/6R\x0c\x92\xb9\x8cj.\x9f" + + "k\xaa\xcb\xf1\x89\xb4\xaag\xd5T;g5\x96\xad\x9a" + + "vn\x99\xd1o\xd9Zb9\xabiD\xd6\x9dK\x19" + + "z\xb7fg\x93\xa0\xe9j\xaaU\xd5y$\xdb\xcbM" + + "oY$wYp>\xe2Z\x8a\xcb\xba\x9d3\xb9\x95" + + "M\xf3v\xce\xeaVd5\x93'sI2p\x1b5" + + "\xb0P\xf1\xb4y\x12\xa6\x0f\x82\xcd\x18\x04\x9b\xe9`\x0b" + + "u0\xb9\x951tK\x0b\xf7\xf2\xe9\x83\xa23\x06E" + + "g\xe6:y\xca\xe8\x8b\xdb\\\xe6\xa6P'RF\xdf" + + "\\\xd5\xb6\xb9\xd9/d[\x04\xcd\xb8\x9c\x9aH\xccS" + + "\xb3)\xf2\xaf\xe5\x84\x93\xb0Q\x05[\xa5\x85\xd1 \x99" + + "K\x18\xe9t\xb3eeq\xda\xdc\xbf\x81\xd7\xf7v\xcf" + + "3\xf9\x0a\xc6r\xb6a4j\x96m\xb2\x1a\xea{." + + "cX\\\xe7v3\xab\xd3\x85qd\x19Y:\x83\x96" + + "\xbc\x19\x0b\x08h\xa4\xcb\x16U\xe7\x0d\xd0\xa3\xea\xdd\xbc" + + "\x85w\x81]\x80\xb5k\xddr\x8f\x9dK!\xd2\xa3\xea" + + "L\xee\xe6\xb9\x94\xd1\xd7\x8az\x19\x83\xfe\x9ce\x1b\x89" + + "\xe5\xf5\xbc\x931\x16N%\xfbP3^\xa8\x9b\x175" + + "2\x0e\xc9\x9c\xc9Sj\x7f\xab\x9a\x82\xae\xac\x9e@\xab" + + "\x91v\xbd\x91X>/\xd1\xc7\x18[M\x94\x93\xcd\xe4" + + "\x9c\x7f/e\x11\xa3A5\xbd\x9f`8\x8a\x15=\xe6" + + "bq\x9eX\x90\xb8\x84S\xb7\x09ke5\xaaes" + + "3\xdc\x95\xe8\x13\xf4\x15WmV\x975\xd1\xbc\x14\x8b" + + "\xd8\xa4w\x83\xda\xcd\xc5*\xb2\x1a\xdd\xb8(c9\x0c" + + "\xc3\xccJ\x9a\xc5\x91e\xb04Z\xec\xc9\x16\xb5\xa6\xbb" + + "[\xd3\xbbs\xc2\xee\x9f\xa7\xca\xa9\x94\xa6w\xfbn\x15" + + "\xd6\xa5\xea\xadj\xaa+['\x06\x95K\xa8in\xaa" + + "\xad*\xa4\x9cq\x82\x8b\xcd3e5\xcd\xdbQW\xca" + + "\x90\x9f\xde\xba\xd4\xb0\x85\xc3\x1b\xbasI\xd5\xeaI\xa8" + + "\xe9V\x16&\x86\xc5S]H\x87\xc0\x9b\xc9\\N\xd5" + + "h\xab\xb0\x1bY\xab\x93XfP\x9fr\x18J+2" + + "\x14\xda\xce\xc8X\xe7f\xadV\x8d\xd5X\x16>\xe5\xb7" + + "\x96lQq<\xd0\xedl\xaf\xb9)V\x83\xeb\x93t" + + "\xf6\xa2\x96fu\xbcEKkv\xae\x97\xf7h\x89\x14" + + "\x8f\x03\x11\xb1\xd5\xac;\xc6y\xca1\xfa\xc3\xc9\x0e\x9e" + + "\xce\x18\xa6j\xf6\x0b.\xee\x16$\xdb\xb8\x99Vu\xae" + + "\xdb\x02\xcf\xa8\xa6\x9a\xb6\xfc\xda5\x04\xe7\x1c\xb8\x0d\xdc" + + "\xda\x0e\xae&\xec\xacj\x1b\xa6l\xd5g\xb4\x00_`" + + "\xdc\xca\xd4'l\x1cE.\xc3M\xcb\xd0\xd5\x14hv" + + "?\xd2Y\xb7\xcc\x93a\x95w\x0an5\x90\xd1\xd3\xe0" + + "\x1a5\x8b\xd5\x89\x03\xa8\\\xd6\xe2\xe6\\\xc3X\xce\"" + + "i\xd5\\\x9e\xe3+q9\xb0\xe9zz\xbb&\x1bz" + + "N\xcd&5c\x1e\xe7r\xb2SM,\x0f,9Q" + + "m\xcbr\x15\xac\x9c\xa3\xde\xb7\x86U\x9d#Kc\x9d" + + "Z7\xf9zZ\x0c5\x89\xdc\xd6\xfd\xdd\xce\xd5d\x7f" + + "\xa0\x0d\x17\xaf\x9b\xa7j(\x03\x12\xaa\x89\xd4\xc0YX" + + "M\xf6\x9f\xc6\xb2h\xc7\xc1\x09\xb3\xc2\xf5!\xb9^\xbd" + + "\xb0\xcd\x93\xb1J9T!;.\xa0\xc9A\xbf\xbcp" + + "'G\xd7\xcc\x08\xfa\xe5\xc5a_t\xdd\x8c\xa0_^" + + "\x1c\xf4\xe5\xf9\xe5\xa7\x87.\x04q \xb2q\x9c\xef\x98" + + "\x8f\xa8\xed<\xe5\x99\xc2*\xf6\xc7\xfb\x95lS\xed\x1e" + + "\xcf\xd3\xd4\xdb\xa2zn'\xdc\x95\x03\xceC\x06\xfa\x95" + + "Z\xd5\x0c\x0e.@\xe3h97z\x96\xf3\x11\xb2l" + + "\x9fB\x0b\xf3\xc5\xa0\xe5|\x94,\xe4\xe7\x11\x7f\x95," + + "X\xc7ks\x9c\xbc9/#\xfe6Y\xb0\x8e\xd7\xe6" + + "M\xb2l\xdf@\xfc=\xb2`%a9\xbfK\x96\xf9" + + "\xdb\xdeyf\x990\x9cO\x12\xfcg\x84K$\x09\xa2" + + "C@\x18\xceE\xd2\x0c\xc6\xda%\x19\xe2\xa3\x11\x1e\xea" + + "\x84\xcc\x8d\x94\xe6\xa2\xbd\x8e\xf8Y\x88\x97;>\x9b1" + + "\x12\xf6f4\xe2\xe7!>,\xe4\x84\xccIh7\x9f" + + "\x8bx\x1b\xe2\x11Y\xf8lZ%\x1cU\x0b\xe2\x97#" + + "^!\x09\x9f\xcdBi>c\xf1\x0e\xc4\xafD\\\x92" + + "\x85\xcff\xa9t\x1bc\xf1+\x11O!.\x17\x8b\x80" + + "9\x8d\xda\xefA\xdc\x96\x9c\xd3\x87a\x8c)+\xa4\xbb" + + "\x19\x8b\xdb\x88_\x8bxQX\x04\xcc]#\xe1,_" + + "\x8d\xf8\x0d\x88\x17\x97\x88\x80\xb9u\xd2c\x8c\xc5o@" + + "|\xb3$\x81\xe0\xfd-Z\x1a4\x9b\x1c\xb0\xfe\xe1\x9d" + + "[\xc2d\xcd\xf6=-\xbe5\x96\x17\x1d\xe6\x17\x00\xf7" + + "H\xa9O\xedoNz>\x7f\xb4\xc6./\x0c\x93A" + + "pq\xa1+3\xa5Z\xf6E\x19\x0b*\x82\xb7\x0b\xc9" + + "\xd2\xc3\xea\x0dY\xb3\x97\xd5\xe1\xbbxas~y\x0d" + + "\x95\x17\x16'5\xcb\xee0:\xb2L6u\xdf\xa7\xa1" + + "f\xc4\xc8Y\xc1\xd8\xeb\x93\xbd\xa0Y\x86\xd9\xbf\x88\xb4" + + "\xb2\x01\x85\xac\x86J\xbd\x86\x02SY\xdf\xc3\xd5\xe4\xa2" + + "H\xde\x0c\x15\x16\xb3\x01\x0fJN\x09\xaa\x10\xaa\x9e\xe0" + + "l@,L\xe8\xb4~\xe9z!\x95\x0b\x82\x9b60" + + "\x16\xbbX\x86XG\xc0\x13\x1d\xbb\x93\xb1X\x87\x1b\xdd" + + "t\xa1\x13\xdd\xb4\xc4\xf7Y\xe7\x92\xdcB\x9d\xad\x01\x9c" + + "5\x0d\x86\xeb8e\xf5\x90H\xf0\x147U;\xac\x19" + + "\xfe\\\x8a\xa3\xe0\xb8\xcdd#3\x80U\x148\xd7P" + + "\xb5\xb0\x88\x05\xd6\x89\x93\x8d\xa0\x0b\xdd\x0c\x9c\xf3\xba\x1d" + + "\xd7V1\x16\xeb\x11\x11X\xde\xe1\xef\x8a\x9b\x19\x8b\xd9" + + "\xae\x0f]\x1c\xc9E\xaf\xb9\xd9g\x8b\xb9N\xc3\xb0)" + + "\xe6\xa8\xe6RU7,\xefh*m\xe8\x86m\xe8\x1a" + + "\xabK\x0c^\x00\x89v\xb5\x0f\x8b X\x96\xe4\xe9\x85" + + "\x19\x1b\xb44w\"\x04\xbd\xb2\xc1\xc7\xb9\xd0\xea\x14\\" + + "\xbf\x91GP\x0b\xc1\x15:\xcb\x1b\xe83\xb3}\x8f\x90" + + "7\xd0\xa3\xb3\xfd@\x1e/\xfe\xec\xd8|?\x8e\xc7\xf5" + + "\\G_kg,\xf6\xaa\x0c\xb1?#KpB\xaf" + + "N\xb4\x8b\x88\x94\xd8\x07\x12@\xb1\x90\x1e'\xe7\xfa\xde" + + "!\xf2c\xa3\xf4\xf8p\x19c\xb1\x0fdh\x0f\x1cC" + + "FO\xe1,\x7f\x8e\\\x12$\xa8\xeb\xccZz t" + + "4\xc9{\x03?s\xbd\\O\x1a\xa68K\xf4|s" + + "\xa6\x91\xcc&\xc4\xb1\xa1\xe7\x83C\x02o\xed\xcc0\xf0" + + "\xe2LW;\xf5\xdc\xa8\x03\xb2B\xba\xd4\x84\xcd\"Y" + + "\x93\x9b\x1e\x9c\xd2\xf4\xe5\xa8Z\xb0:S\xc4\x9f\xbam" + + "\x0e.e\x07=G\x9bZ\x9f\xe2\xa6]\xd3\xc2{y" + + "\x8a\x8ejD\xd8\xdad:\xdf\x18;\x8e\xce7F\x8e" + + "\xa3C\xc3\xe8\x0c\xc6\"\xba\xa1\xf30\xfe\xcf\xee3j" + + "\xec\x1e\x93\xf3/\x10w\x8d\xa8\x19\x934'?:\x04" + + "OP:\xc5\x09J\xbb8A\x99K'(\xdc\xb2\xb5" + + "\xb4\xcaP\xe6\xe7\xc4\xdf6g\x90\\\xed(\xe6_\xf0" + + "\xa6\x06\xd7\x0e4t\x11SEg%~\x9a\x00\x98\xed" + + "\x9e\x90L\x94CP\x0a\x81l\x0aJ),aR\xd4" + + "\x8d<\xf8p~`\xe1%\xe7\xe0\xe9\x14\x92\xc8'n" + + " \x93{\x06\x02(\xad\xdb\xbd\xc3\xf0\"\xe7\xb0z$" + + "\x1di\x8c\xf0\x0f\xb7\x8b\x84x\x9cN\xc2z\x9a{(" + + "M\x84\x8a\xe2\xb1\x99\xdc\xd3\x17#\xdeA\xd4&\"\xca" + + "\x95\x18\xc5Iu \x9e\x01\x09*@H\xc74\xc9\xf6" + + "\x14\xc2+I\xe6\x87\x85t\xcc\xd2\xc9\x0b\x9d\xd4\xdc\x08" + + "R~@\x04Z\xcd\x0d\xfd\x89T06euBM" + + "\xb5q3\x01\x12\x93@\xa2\xf8\x15\xdb\xd4tK\x83D" + + "\xabj\x9b\xda\xca\x01q:f\xa6\x9f\xe6\x19\x1b9]" + + "Q]\xcf4\xd2 \x8e&\x9b\xb2" + + "\xe1\x14\x1f\x18\x18\xaa\x92s9\x8b\x1b$\xe2/\xa98" + + "\xb2\xaf\xeb\xe1Zw\x8f}\xba\x93=\xf9t\x0el\xd9" + + "\xe6\xb1J\x08\xdc\xea\x8a\x8e]\xeb\xbbW\xa3co\xf3" + + "]\xb5\xd1\x097\xfb\x8e\xd9\xe8\xa4\x9b}\x17kt\xca" + + "\xfd\xb9\x16\xa1'\xb7\xc9\xcd\x8d\xc2[\xec\x00\x1d\x8e\xeb" + + "\x16\xdf\xe4V\xaa\x07\xc7\x1bl\x83\x875\x82\xe3\x02\x0e" + + "`\xbepq\x8er\xcf\x91CP\x06\x81\xbc>\xca\x04" + + "\xa2Y\x87\xa7+QR\x0f\xfd\xb0\x8c\x90\x13fQ\x10" + + "\x96QQ^\x09\xa3)*\xe3\xc9\xbc\xe8\x0biJ%" + + "\x9cI\x04\xba!\xef\x9c\xa4\xa8\xa6\x12\xc6\xd29\xc9\x92" + + "\xbcs\x92\xe2q\x950\x81\xceI\xda\xf3\xceI\xa0\xb2" + + "\x12\x15I\xa5\x95\x08\xb7\x0d\xf1+@\x82\xe9%\x87\xa5" + + "J\x98\xc9\x98\xb2\x98\x1a\xf2\xcf$q\x1fz\x99$\x15" + + "\x15\xeedR4|N%\xcc!\xea\xdf\xe0R\xff\x95" + + "\x03\xc89\x9b\xa9G\x19\xdb\xc0\xe4\xb4\xa7\x9d\xe7\xb2\xda" + + " \xa0\xeb\xa0\x914]M\xb5\xa5T\xbd\xd5\xd0\x0d'" + + "\xcc\xd6\x15NX\x07i\x03L#\xe5\xb8\xfc!\x92[" + + "\xbb\xf6\xa6k6\xcd\x8e\xbc\xe1\x06\x87d\xbb\x06i~" + + "\x10\xd5\xce5\x9d\xda\xc0}[8\x18\xed\xdfe\x98\x09" + + "\xde\xc8\x13L\xe6)O\x0dp\x0fS@Ph\xdc\x0e" + + "\xab6\xffB]cp\x0a\x0f0]\xd9V\x89\x07\xfa" + + "y$}\x1e\x18\x90\xb1\xcb\x02\xe2\xd4\x95\xb1\xc7:\x03" + + "\xe2T\x0a\x09\xbe\xf8\xdal\xff\xc4\xc5=\xa1\x8b\xbey" + + "w@\x9c\x16\x09\x11{r\xb6\x10\xa7$$I\x17G" + + "R,\x82\xc7\xf2\"\x8a\xdc\xb3\xb9(\x9d#\xfbg\x82" + + "\xe1\"\xc1D\xab\x08\xf7H\xda\x9d\xa1F\x16\xc1\xe1y" + + "\xd30(_\xa9\xb3\xc4\xa9m\xc4\x1f\xbc\xb3\x86)o" + + "\xd3\xa5\xd4\xfe&\xcb\xd6\"(b\xbcc\xd9\x8c\xa1\x05" + + "b:\\f\xe2>$\xb9\x0f\xe13q\xdbWR\x0b" + + "9iaL\xdd\x17\xc8cM\xef\xf64\xd5\xa9-\xaa" + + "\xce[4\x9d\xb7ry@\xd8\xdc\x8c\xffq\xc4\xdf\xfc" + + "\x80&\xe8\xae\xd3\x0aT{22\xc4\xae\x96\xa0&\xc5" + + "\xbb\xec\xc5\xde\x98M\xe4\x9f\x8b}\xe2\xe5]v\x9bi" + + "\x10\x8fw1\xaa\xd2f\x1a\x0c:\xff\x0e\xfd\xf9\x86\xbc" + + "\x10\xc0^r\xb1(\xcc\xcf\xb9\xa6=cN\x9c\x0e\x04" + + "\xb2\xabD\xafA\x86\xe6\xca[mn0lQ\x18\xaf" + + "\xd1\xf4\\\x7fd\x15\"\xac \xbab\x89?0r\x07" + + "\x943\x16\xed\xef\xf4}\x04y|cu\x8a\xab\xc9\x05" + + ":\x87\x0a\xbfg\xc2z\xa2\x92\x8e>c`I.\x9d" + + "\x14,\x83\xc9\x81]L\xee\x98&\xd3da\xc3Dc" + + "lO\xefC\x7f\xea\xef\xda\xfdv\xe1\xb1\x9b<\x88\x06" + + "VoY\x9aUCV\x0c.r\x89\xb7\xc8\x93n\x0e" + + "^\x16p\x16y\xd6m\x8c\xc5\xce\x93!\xd6(\x89\xd5" + + "A*\x81F\x9eQM;k\x02\xf7x\x08\xadR\x8b" + + "\xaa\x03w\x0ae\x93\xff\x1d\x97D\xdcq\x9f\x89\xd3\xc3" + + "<{#$\x87*B\xa4\xb7D\xcbq\x8e\x87\xca\x10" + + "\x1b!ANEu1nd\x99\xac'!\x92\xfb\xc7" + + "\x99\x97nI\xbd\xbe\xebCw\x83\x0dN\xe9\xcd\xba&" + + "\xc2Y\x1bz\xba\xba\xccz=i\x1aZ\xb2i\xa5m" + + "\xaad\x94\x05\"\x92\x9e$\xda\x10\xa6\x96\x9aJ5\xa8" + + "inJjC\x8fJ\x0eoS\xb3l-!\xc2\xd9" + + "\xbd\x9b\xbb\x8c]\x08Q\xa8\x89\x85$\x08\x82Q8;" + + "V\x02@\x13\x0c\xb4\x97\xc0Q\x9c\xa5/8\x18mq" + + "\xfc\xbb\xdd\xbcQ3\xb9\xe3\xcd\x0dh\xadB/\xae\x12" + + "wL\xca]\x858\x82\xebRC\x0bp\x9a\x95\xbf\xa8" + + "-~ikS\xbd \xff\x02C\xb4\xdd\xb9Q\xd3\x16" + + "X\xf5V\xd3\x8f\x7fuC\xa2\x16N\xf6\xc3_\xfd\xe0" + + "A\xc8\xb8\x91\xa3\xe4\xc0L]\xa6\xa6XM*x\xc1" + + ",\xa2\xa7\xb9\xea\x19\x0d\xa7\xb9\xccB\x0a\x98 \x83K" + + "\xb9\xddg\x98\xcb#\xcdz\x97\x81]\x1d\xe1uu\xeb" + + "\x12?R\xce\xeb\xea\x8e\xf9\x81P9\x97\x0b\xdd\x85}" + + "\xdd)C\xec>\x09\xc0aB{p\xff\xee\x96!\xf6" + + "@\xc0 \xdb;\xc3\x8f\xa9#\x0d\x1a-\xb2}\x08\xde" + + "'C\xeca\x1c)O\xf4\xe8F\xca`rw\xbf7" + + "\x0a#\x83\xf65\x9d\xb0\xb9X\xa4S\xd5\x93\xee\x8f\xd5" + + "\x89\x1eU\xd7y\xca5\x89jP\xb9\xf5&\xa1\xc6\xa2" + + "\xd3\xf2/\x9e\x12\x8fh\xc5\xdct\xf4g\xb8X\xba\xb3" + + "h\x84\x8bE\\eL\x98H\xcd\xcb\xc8Dj\xa2\xd3" + + "\xf1h\xbd\xb8nt\xfe(\x8a\xab\x9c>\x99\xe2*\xd1" + + "\xa6rC(\xc3:7r\x09g3\xb0\x08n\x07\xf1" + + "\xb3\xd9\xb0\x18c\x11[Khr&\x11\xb1\xb5UZ" + + "$\xad%\xb4/\xb8\x83\x94'BZy\x9d\xad\xbaQ" + + "\xd7\x01\xce\xb2\x96\xb1\xd8D\x19b\xe7\x06\x16n\xfa\x9d" + + "\x81kH\x81\x83\x0d\xc1\xbf!\xe2'N\xf3\xa4\xa7W" + + "G\xec\x0e\xf2oD\xfc\x94\xc8_\xc8\x04\x0a\x98\x0d\xd9" + + "\x9d\xce-\x96\xc0\x06\x9b-6\x98\x88V\x8d\xceg\xac" + + "N7\xcc\xb4\x9a\"\xc7v\x9bi\xa4\x99\x9c\xb1s\x09" + + "S\xb3\xb5\x84\x9a\xa2\xd3\xc3/\xb8\x9d\x95g\xec\xba:" + + "\xbf\x9f\x83{\xec\x92\xc0-\xf2\xb1\x1b\xfc+\xd3\xa8\xf3" + + "{9\x13\xa2\x93\xee\xf7S\xb1E\xa7l\xc8Q\xd7[" + + "x/\xaap9\xf7\x15\xa0w\xb7\x19)-\xd1\xcfX" + + "n\x91\x86\xe2\xbf\xcd\x00\xfc\xed\xe8\xf6\x97\xf5p\x9e\xb2" + + "\x8d,$zD=\xa1\xdb\xe7\x1a\x02\x87\x9c\x8e\xf2\x19" + + "\xbb\xc0s\x08o!5\xc8\x0b\x83\x83a\x10\xc8\xcb\xaa" + + "l%+\xa0X\x08Me\x1d\xd9\x9d\x81\x10;\xc7\xe9" + + "\xbb\x91\x9c\xca\x81\x10;\xe7\xa6\xf4\x16\xd2\xc67{\xb7" + + "dJ\x9d \xec\xed\x142\x17\x08\xb1\x93\x85J\xb6\x8b" + + "\xbc\xc4w ~\x0f\xf6\xc5\x89\x96\xba\x8b\xccZ?\xf2" + + "n(\x08\xb3v/E\xe4y\x11v\xd1rI\x98\xb5" + + "\x8fP$ \xdd\xb5y\x0a\x1c\xef.\xda\xb5\x87IC" + + "\xf4}\xdfr\x89\xb0k\x8f\x92y\xec\xfb\xbeC\xce5" + + "\xe9\xe34,\xdf\xf7]\xe4x}\xdf\x84\xbb\x83>\xee" + + "(\x94\x09\xaf\xefI\x1a\xd6{\x88\x7f\x0e\x12\xacN\x19" + + "\x89\xe5F\xd6\xf6Dd\x9e\x81\xa1\xa6\xfa\xd4~k\x81" + + "\x1et|\xba\x18\xb4\x88'\x83%>A@\xc4'0" + + "g?\xa8\x09\x9b.^\xb2\x08\xae;D|\xa2\x13\x15" + + "j4\xab\xfd\xe2F_\x90\xf7$\x1d[Z84\xa0" + + "\xc2'?G\xbd\xe8\x1dH`P\xe1\x93\xafS\xabo" + + "p\x92\x83\x0a\x9f\xb6\xddh&1\xa2VI\xd3\xb36" + + "\xb7\xdayZ\xd5\xc4u\x15\xd79@C\x9c\xd9`0" + + "\x8aAvQ\xddh\xa7\xa3d\xb08y\xa0\xd8`%" + + "\xf3\xc8\xe2\x89\xf0D\xd0\xe0\x11/l`\x11#\xd8\xde" + + "\xe01\xcds\x0d\x03\xec\x82\xeb\x19\xa6\x7f\xe2C\x8a\xa4" + + "\x97\x09(\xba\x8e,ci\xa0\xe2\xeb\xdd\xbf\xec\x9f\xed" + + "\xf8E\x9fp\xec\x1b\x949\x87P\x8c=\xee\x98!\xb9" + + ">5\x95\x1a\xcc1\x9aG$)5\xab'zZ\x0c" + + "\x06\xdd\xae,\xa9\xcbX\xb6a\xf2\xff\x1f\xfaI\xb9\xab" + + "\x9f\x18\xe9\xb4J\xf7\xb7\xd9\xff\x8b\xd6\x06\xd5JZ\xd5" + + "L;\xd7\x93\xdc\x14\x06\xe7\x179\xc8%\xc7A\xbe\xc4" + + "\xd7Ah\xe7\xba\xa2\xd0\xf5\x9a{\xa7\xa80\x88\xa1m" + + "\xd2\xcb\x1cU\xda5\x9e\x0a\xeef\x9c\xa6\xab\x81\x8bQ" + + "t\xab\x08G\xeb'u\x8b\x96\xb6\x07\x92\xa6\x95.\xcb" + + "\x89\xea\x8b8\x83\x84\xf3w\xdc`\x91\xac\x99\xe0\xb1s" + + "\xe5\x10\x0c\x85\xc0\xb7J\x94\xa5\xc8F+\x9c\xa3\xb3f" + + "rjx\xde\xb8r\xc8\x89\xcb\xa2J\x8c\xf8\x87\xe7\xd5" + + "(\x97\xfe&\xee\x8b*\x8b\x89\xefz^\x8dr\xf9\x94" + + "\xb82\xaa\xa8\xc4\xb9\xbcX\xeb\xf2\xd0\xe79\xc1I5" + + "\x8a\xcdN\xba\x9e=J\x15QB\xae\xbd\xd9\xc1 \xec" + + "\xf2\xa2\xbf\xe6\x04/]A\xaf\xf0\xa2\xb0\xcb\x8b?\xcb" + + "\x09\xa6\xd9O\xcc\xeej,\xb8\x01\x0b\xc2\x9f\xe6\x04\xd7" + + "\\G\xee\x93\x1b\xb0`3H0\xa6\xe4\x93\\X\xf0" + + "\xcdM4@O\xa4\x8c)\xfd\x18K\x86Ql\xf5\x8c" + + "\xa0@\x18S\xf6Q\xce91\xdbN#\xf1DB\xfe" + + "6\x18L\x15U\x9d#\x10Te\x88\x83yK\xe5Z" + + "Uj\xb7\xcem-!\xc8\xbb\xb0\xd405\xae\xdb\xaa" + + "\xcd\xc2\x83>\x1d\xe9\xee7\x8d\x81\xb0\x7fU\xde\xa3\x05" + + "\x87\x03gLnY\xe4@a_\xd0\x17X\xe8\xc4\xec" + + "\x8b\xebm\x03+\xe2k\xb1\x0e\x08\x91\xcd\x93\x836\x97" + + "1\x8d\x95ZZ\xb3\x99\x7f\xbd\xbf&E^J\xd7x" + + "\xb6y\x9a\xf4W\x16\xce\x9a\xfc\xef\x1cd\xc5\xb9nk" + + ":OMu\xff\xe8\xe8\x973<\xe0\xaa_F\x1a\xd3" + + "\x04\xa11\x8d]Ez\xe8\x98e\x8c\xe5\xb8\x9e\\\xd0" + + "\x15\xe7\xdd\x8c.\x0f\x88\x9f\xedh\xb9\xd9\\\x04\x95," + + "\xe8\x8a\xb3:qk\xc9\x05\xda\x91!\xdb\xfc\x7f\x14\x01" + + "\xecz5\xc9\xa9\x19\x19\xe4b\xe6\xec\xc1\xae\xd0m\x08" + + "\\\x8cs\xad\x85\x8d\xb3\x83\x970\x1d\x1f\xc0\xa6\xf6\xc0" + + "]\x1d\xd7\\\xd8\xfa\x18c\xb1m2\xc4vKP'" + + "\xe4\xaa\x7f\x88hs\x8e\xaa\x1eP\x8f\x1ay\xb7\xef\xc2" + + "\xa83\xb2v&\xeb/\x80\xa5\xda\x148\xc3 9\xe0" + + "q\xc9y\x9c|o\xd8\xca\xdf_\xa0\xbc+\x9bq\xae" + + "\xd7\x11\xefI\x14\xe8\xe0\xc3\x19\x8b\x8d\x17\xea6\xfe\x9f" + + "\x9f\xa02:g\x09\x93\xa0w\xc0\x89l\x9e\x03\x7f\xd0" + + "w_\xaa\xf66\xeb\x96mf\xc9R%\x07\xd2\x00\xf3" + + "r\x89\x9f\xb0\xc1]\x84\xa5\xb3\x9d|\x0d\xc9\xc0!\x9a" + + "\xba\xd6\xf7&\xe5\x92\x8e\xf5\xcbd\xdd\xf3\x87E\xfct" + + "r\xe2JP\xe1\x02\x88\x9f\x8d\x1a\xb8\x96s\xc1#\x91" + + "\xd3;F|\xf3\x93\xb1\xd8\x08\xf02\x0dG'u\x06" + + "\xbe\x9d0\xc9\x0c$h\x9f\xd4\x19H\x82:i\xad\xff" + + "\x01\x15,\xf1\xf2\xd4G'-\xcbu\xf4p4!\x96" + + "\xb0\xb0\xa1s\xf7W\x9c\xd5\x90\xf1\x91s\xcc\xdd\x0e\x16" + + "\xee\xcfp\xf7W\\\xb2M\xaew\xdb=\xcc\x01\x9a\xc3" + + "z\x97\xe1\x952$w+v\xa3\x1c\x82q\x10H\xf5" + + "\xa6\x1c\x92Q\xfb\x18\xe2\x9c\x04\xed\x95\x91\x09? \xa3" + + "\x0a,K\x10=k\x88\xa3\x02\xcb\x0f\xa1\x0a\x8c\xf8S" + + "\x94[\xe8QG\x05\xa6\x8c@~\xe6\x9c\xb2\x90`\xd9" + + "G(\xe3\xcdS\x88\xbf\x88xM\xb9`\xd8G)#" + + "\x90\x9fQg\xa8\x93\xb1\xa70\xa3\x8e\x11\xf1\xc6\x90\x93\x10h4cJ" + + "}\x08\xbbs!\xe2-!g\x93\xd7\xa0\x08&\xfcb" + + "\xc4;\x10/)\xad\x84\xb3P\x02\x87pX\x1d\x88_" + + "\x89x\xf9\x14q>\xb14\x84\xfd\xbc\x02\xf1\x9e\x90\x13" + + "w2\x8e1\x11\x14\x1dO\"~-\xe2\xd5\xc5\x950" + + "\x9e1\xe5\x9a\x10\x1a>W#~+\xe2c\xdb\xc4y" + + "\xc6\x96\x10Z \xb7\"\xbe\x13\xf13\xc3\x95\xf0\x15\xc6" + + "\x94\x1d!\x94\xfcw \xfe0\xe2#J*\xe1l\xc6" + + "\x94\x03!\x94\xa4\xfb\x11\x7f\x1e\xf1hU%LdL" + + "y\x86\xda\x7f\x1a\xf1\x97\x11\x0f?^\x09\x93(\xa8\x1e" + + "-\xa5\x17\x11\x7f\x03\xf1\xe1gT\xa2\"\xa0\xbc\x16\xc2" + + "e|\x15\xf1?#^\\Z\x09_\xc5\xe5\xa2\xf7\xbe" + + "\x8d\xf8\x07\x88\x8f\xa9\xae\x84sp\xb9h>\xdfC\xfc" + + "\xf3\x90\x04\x15\x93*a\x0ac\xca\xa7\xf4\xdaO\x10\x0e" + + "\x15I\x10\x1d9\xa2\x12\xa62\xa6@Q'c\xedE" + + "2\xc4\x87\"\x93q\xf8\x94\xb8\xcd\xb3\xd0" + + "\x02\xb5[tE\x0e\x9a=A\x96\x01\x11\x9f)9\x0f" + + "\x1b]]\xa6\xa1&\xdb\xc0\xe8\xe3\xe6BK\xed\x8e\xf0" + + "\x85}=\x9e\x86\xeb<\x1e\x07\x97\xc7@\xc4ge." + + "\x9fTM\x0a\xc2\x05\xb3\xbfA\xcd\xa8\x09\xad\xc6\xee\x0f" + + "\xb6\x91\xc8d;x:\xd30\xc8Yl\xf7\xe9\x8b\x06" + + "\xbf\xa3\xe4\xf4\xa7\x99!\x8fC\x85\xc6\xe5\xa4\xaeu\xa8" + + "Zv\xbd\xdd\xc3AW\xdb4\xbd\xbbC\x93\xf3\xb2W" + + "\x15\xdeZ\xf2\x8c\xb9\x01%No$\xb77F\x92\xa7" + + ";x\x9a\xc9\x99\x86\x01\x091\x12&\xe7\xfa\\SB" + + "\xc5I\xe7\x965\xa0y\xdb\xe5\xea\x11C\x0f\xdc[u" + + "%\x87sk5\x93\xd6\x128\x1b\x0c\x06\xbcb\xd0\xab" + + "Y\xce\\\xb4\xb2:ns3HLF\xba\x0d\x1f`" + + "5\x8d\xa6:\xf0\x01G$@\x85/z<\xedr\xa5" + + "\xb7\x1c~\xa4\x90p)2\x99\xe8\xc7\xfb\x98\x97\xb3\xf8" + + "\x9an\xab\xcby\xe12\xf1\x95=j\xd6\xb2;X$" + + "\xef\xdeY\xb7nY\xee\x08\xbd\xf6\xad\xcc\x80wv\x1a" + + "\xb6m\xa4\xe3\x06\xab\xa3\x09\xf1+'\x9c\xab|\xd0f" + + "r\x8b\xa6\xd8\x1ds\xd6\x89\xcf\x11j\xb3\xf7q\xbb\x82" + + "3\x8e|c\xbd>\x9b\xac\xd3\x8cA\\\x90\x93\x1d\xf5" + + "g\x9a\xaf\x87LY\xe2\x1fxD\x92\xaa\xad\xbaI\x1b" + + "r\x96\x9a\xce\xa4x\xbb\xb8\x18\xf5\xc57\x9e[\xd5L" + + "\xdd\xd4&\xdd6\xfb\x0b^8\xce\x7f\xa1\xa7~N\x99" + + "\xe1;B\xc3\xcby?\x0c\x87<;\x1a\x86{y\x16" + + "\x86\x17\x0d,:M\x17.U{k\xdaQo\x16\x87" + + "^\xee'@\xa2\xb0$\xd7`\x18fR\xd3i \xc1" + + "\x83\x8eN\xe7Le\xa2\x84\xa6\xbeS'l\x07/`" + + "{\xed|\xe1\x05\xecAur\xba\x9c\xe0\xeb\xe4\x81s" + + "\xc4\xd9\x83\x9d#n\x18,xl\xb6\x9f$\xc4\xd3\xc9" + + "\xb3\xed~D\xd9\xffc\xf5{\xf0\xd1}\xc1\xd5h\xc6" + + "\xc8\x07\xe0%&\x8d\x96\xae\xf2SiGK;s\xed" + + "<\xc1\xb5^n\xba\xb7x\xbdLU,\xccu;x" + + "\xac\x81C\xdd,C\xec\x0e\x9c\x94\x90\x98\x94\xeds\x03" + + "g\x1dR\x91\x98\x94\x1d\x9d\xfeY\x87{\xacq\xd7\xaa" + + "\xe0\xb1\xc6P\xe7Xcn\xf0X\x03\x9cc\x8de\x8c" + + "\xc5\x1e\x90!\xf6\xb4\x04uf\xa2\xb7\xc3\xe8\xf3n\x08" + + "\x17f\xd9Kq5\x13\xe7\x09\x83Q\x9a:\x175\x0b" + + "\x86\x04\x15\xfe\xf8\x9d\x83L=\x9b\xc6qzqhn" + + "\xaa*\x16\xc9\xcfW\xe0MU\x01u\xc9\xa7I.\xc1" + + "\xc8w\xee\xa7)\x1e\xdb\x19\xf8V\xca\xd8\xf6\xc0\x97T" + + "\xc7\xb6\x07\x12\xf6\x8e5\xfd|\xb9\xf8\x83\xee\x90\xc4m" + + "\xa4\xf5\xac%~u\xf4g\x18\xf0\x9c\x9b\xbc\x02\xff\xbe" + + "X5\x91\xe7{::\x955\xa8:s\x02b\xae\x95" + + "C\xf0%r\x90\x17&\xd1\x1c\xedDLg\x09\xcf " + + "~\xb5,A\x85\x88\xe5T\xfaeTzV\"|\x1d" + + "\xe5\xb2\xac\x17^\x9f5\xa4\xea^\x8b\xf8\x8d\xb2\x04P" + + "\x03\x81T\xdb\xcaz\xd2\xea\xc1\xf1\x83gI\xab\xf7\xdb" + + "\x90\xc49\xa9\xb2\x86\xf0\xeb\x10\xbfIvr\xc1\xa0\xb6" + + "\xbfQn\xcf\xcb\xcf\x19j\x12Z\xfd\x16\xd2\xc6\xfd\xfc" + + "\x9c\xd5\xc3\x84V\xbf\x9d\xf0m\x88\xef\xa6\xcc\xa6\x11\xe1" + + "\x84\xd9E\xf8N\xc4\xef\xa3\xcc\xa6\xf3D\xd8\xf2\x1ez" + + "\xaf\x9f\x9f3\\\"\xf2|\x1e\xa0L\xa8\x9e\xf5\x01%" + + "\"\xcd\xe7#\x04\xefG\xf8yJ\xdbY*\x8c\x86g" + + "h\x0a\x9eF\xfceJGZ%\xd2y\x1e##\xe3" + + "E\xc4\xdf c\xe5\"aL\xbcF\xb8od\x8c<" + + "C\x18\x13'd\xb4\x0e\xfe\x8c\xf8'\x94\xfes\xa8\xb0" + + "&\xe8\xca\x9cod\x94\x95\x0bc\xe2\x145\xe3\x1b\x19" + + "#\xaa\xdd\xb4\x9d8\xda\x10j\xb3\x15!\xe7B?\x1a" + + "\x0d\xe5\xa4\xfc\x0eE|\x04)\xddP\x09c\x18S\xaa" + + "H\x19\xafD\xfc,R\xae%\x11\xd44\x86\xf0\xd1\x88" + + "O$c\xc512&\x10>\x1e\xf1i!\x09\xa6\x8f" + + "z\x15\x84\x951\x85\xac\x9biXp\x01>0\xd4\x89" + + "\x82:\x9f\xb4\xf4\xf3<+fXE%|y\x10+" + + "&\x12\x15VF\xa1\x15S1^X\x19\xb1\xd0\x86\xa0" + + "\x153}\xcck \xcc\x8c\xa5\xa1']s%\x83\x05" + + "g\xbe\x0e\xc2\xceHS\x81\xed\xda1\xab{\x0dq\x8d" + + "\xdb\x91\x8b\xab\x13Yq}\xdb\x95\x93Z\xb7\xae\x91\xfd" + + "\x1di\xd1\xf4@\x0c\x80{;\xae>\x952\xfax " + + "\x9c=O\x057W\xce\xcdvuq\x13\x16\xf4r\xb3" + + "+e\xf4\x05\x92\xe1\xd8_P\x96\xf1\xf7/D|v" + + "\xe0\xaa4n\x9f\xc2\x0d\xaa\xee\xcb\x0c\xb5\x8b\xdb\xfd\xad" + + "\x06\x0b'\xe9\xe4$\xf6\xc1Kg~\xeb\xcc\x85[\xdc" + + "\xa7\xba\x82\xdc\x02\">\xfbq\xfdz\xa8\x91\xc5\xd5^" + + "\x10w\x16\xc9!\xe7\xe6d\xcdfl-\xedMR\x1d" + + "5\x15\xf0ex\xcc\xcb\xe1\x7f\xa2+\xed+A\\h" + + "K\xfa\x03\xeb\xc9gF\x10\xf1\xd9\x9b\xd3\x8d\x1e\xae\x9a" + + "v'WY\x8d\xddbXv\xe0\\\xc8\xe6\xa6\xae\xda" + + "\xa0\xf5\xf2\xa6\x95\x19n\xd6h\\Op\xef\x9e\xbdx" + + "g\xc7J\x10w\xc9\x02\xef\xd4t\x9b\x9bf6C-" + + "\xfa7P\x9c'\xdaT\x166\xd5t0\x13\x80\xd0M" + + "\x99\x9f3 \xa1:\xc7\x890\x0d*\x82\xdf{\x13\xba" + + "\x9bW:\xfd\x0bKg\x0cR\xea\xcd\x14\xe5\xb7\xf1\xee" + + "O\x05\x82\xf95q?\xaa&?*\xd9\xea\xccN_" + + "d\xa4l\x16F\xe2\xf5F\xd4\x99\x9d1\x08jd\xf5" + + "\xe4\x82\xac\x0d\x99\xacM\xb1\xc9\x81(j\x97\x8e%\x87" + + "\x8e\xdb\x9b\xe2M\xed\x8b\x9a\x1a\xa7\x07\xce\xeaNWg" + + "\x06\xfb{\x19\xd8\x82\x17\x07\x1a\x0c\xbdKK\xe2\x925" + + "\xa4T\xcb\xca\x8b\x04\x11\xd9F\xabf{\x91 a\x93" + + "'\xeb\xfa9\xbe\xaf\xa6\x1b\x8d\x97\xd3d{\x19Ta" + + "kpC\xfc\x1c}\xbb \x8f\xe2l?\xcc\xce\xd3\xda" + + "N\xaee,\xf6\x9e\x0c\xb1\xcf\x03Z\xdb\xa7\x1b\x02\x11" + + "\xea^\"\x8d\"4\xd4)Pyh0;W)\xca" + + "\x83@\x9e\x0e7;W9\xe1\x81X\xbdb7Vo" + + "x~\xac^\xd8\x8d\xd5\x9b\x9d\x17~Z\x02B \x8e" + + "\xa4\x93\x06/\xfct\x10wa\x16G\x0entc\xe1" + + "E\x8a\xc1\x02\x1f\x9d\xe4\xb1n\xde\x9f\x8c\xf7\x97\xe6\xfd" + + "\xd5\xf5\x7fQ;\xa5\x02\x7f\xa4\x15\xd6L\x1eH.+" + + "\x02\x7f(\xbeC\x8a\xd6\x8b,ZsVQ\xb4\xc7\xf9" + + "k)\xdac\xd6|\x11\xed\xd1\xee\x04\x05\xe5\xec\xac\xa9" + + "\xb7\xf0.\xba\xe2\x8c\x7f\xb7k\xdd=\x0c\x02\x17T\xeb" + + "\xe8\x1e\xab\x0fHt\x87\xb5\xc7f\xcb9\xcf\x88's" + + "\xf8\xa7\xfb\xe0\xdf\x0f\xddq|\x9b\x81|E\xce!\xc1" + + "(\x11\xcf\xbf\x8a\xba?f\x09u\x7f\xe4|\xc6dc" + + "y\xaeO5\xd3\x8dMm\xed\xacN\\\xe1\xf3\xeff" + + "\x93\xe3y\x90P\x8b\xfc\xc9j3\x8dH\xa2\xc5\xe8\x8e" + + "\x0d\x85\xc07f\xa3\xd1\xb9\xfe'9\xa2\xe5\xf3\xfd\x14" + + "\xfc\xd1\xf2q\xabE>G+\xd7\xd0\xb6\xb0CKs" + + "\x8b1\x16n\xe5\xe9\xa0\xdfz~ \xd1\xb0\xe7\xb8\x1e" + + "\x17t\\;4\xef\xc5F\xae\x94\x84_\xc4i\xd0\xd7" + + "u\xbd~\x08^\x1fN\xf34T\xf8\x1d\x12|\xad&" + + "c\x1a\x89\x80\x82\xec\x8d\xe4\x0b\x15\xe4@\x82\xe2\x1a\xca" + + "P\x1c\x1b\x01\x81\x0ftD'\xad\xf5\xbf;\x13\x9dt" + + "\xb7\xff\xd9\xd0\xe8\x94gs}%M\xbb\xa7n\x0b\xaf" + + "e\xd1Yk\x03\x9f\xbb\x9ce\x06>b1k\xad\x97" + + "MW\xb6\x9cx\x99\x06\xc34y\xc2\xe6\xc9`v(" + + "\xaf\x9ad\x89\x14\xd2\xde\xa5Lh\xcc\xb9i\x93%:" + + "\x9bmN2\xb7r\x8d\xd5\xd1\x9f\xe1\xde\xb3\xe0<\xcb" + + "\xf2\xd2\xf9\xcc\xcfc\x07\x8e\x854 t\xd7O\xe7c" + + "\x06\xd3\xf9\x80\x97\xcd\xe7\xfe\xbc\xf4\xaeE\xce-\x8a@" + + "z\xd7\x8b\xdd\x8cQE\x14]~[\xfe\xb5\x08'<" + + "\xa5\xe0\x1c6Z\xe28\xdb\x17\x13\xee\x1d\xc3R8K" + + "\xc9 \x19\xafBE\xe2LU\xa3\xf8\x94\x94{tJ" + + "\x86R\x87\x93d\xc9qnyV\x99+\xb0\x9d\x0c\xe7" + + "\x0bXM\x17\xe1^\xde'gA \x99G\x0b>1" + + "y4\xe0\x10\xd3rJ,\xd6f\x80EZQS\x83" + + "\xdc4\x0f*\xfc\xef\xc4:\xa2VT[\xc4!e$" + + "4\xbb\xfft\xd52\x86\xe5(|M\x0d\x83V\xe8\xe5" + + "\xa2\x81\xd3V@U\xa9\xc3\x98\xa7\xb1:\xd3\xb2\xe7i" + + "+}\xa7\x93O\x18D{\x1c\x02\xa3\xf2\xc8\xfc\x8bm" + + "H\xd3@\xf60\x95\xf8\x04\xb7\x88-\xb5y\xd45V" + + "\x1a\xe7^\x1a\x9d(\xf9y\xca&H\x93\x91Z\x10>" + + "G\xf2\xc3\xd0\x95I\xd2\x0cT\xdb\x11\x9f&\x05\xf2\x94" + + "M\xa1\xfa\x13\x11?W\xf2\x0f\x0c\x95\xe9tW\xf5\x1c" + + "\xefN\xaa\x13b\xa8\xcc\x92\xda\xdd;\xa9\x17J\xce%" + + "\x1d\xa4\xae9t7\xf4\x02\xc4/\x96\x9c\xcb8\xf4\xd1" + + "v\x09\xa9\xe5b\xc4;$\x87\xea\x90\xbabtW\xb5" + + "\x0d\xf1+\xa4@\x9e\xb2\xc5\xd4\x1f\xff\x0ekY\x990" + + "\x06\x97\xd2\x9d\xd7+\x10\xef\xa1\xab\xb6\xc5\xe2\xe8\x87S" + + "\x7f\x92\x88g\xe8\xae\xads\xab'-\xcd\xce\xbb\xdbZ" + + "^\"\x8c\xc7\x15\x84\xa7\x10_Iwm\x87\x08\xe31" + + "K\xed\xf8w^#\xe0\xdey\xc5yX\xe9\xdem\xa5" + + "\xbb\xb6h>2\x89w\xa9\xfa\xdb\x08" + + "\x87d\xe7>\xfe\x10\xfa\xa4\xced\xf7\x93:#d\xe7" + + "B>2\x89*y\x86\xfb-\x9cs\xc8u\xe3\x9c\x1b" + + "O\xa2/\xb4\xf8\xdf\xb0\x19V$\x98\xc4,\xf2H\x9d" + + "\x8b\xf8\x85t\x0e\\,\x98\xc4\x1cr\x9a\x9d\x87x#" + + "}I&,\x98D=\xf9h.D\xbc\x85\xbe$\xe3" + + "x\x98\x9a\xc9#u1\xe2\x1d\xf4%\x99R\xc1$b" + + "\xf4\xc5\x18\xffS8J\x99`\x12\x8b\xe9\xbd\x97#\x9e" + + "$\xef\xdb\x10\xf1%\x19\x95\xbcrW\"\x9e\"\x97\xd4" + + "P\xe1z\xd2\xe8\\\xdaw\xee\x9d!\x0b\xd7S\x96\xfa" + + "c{\x9e\xb6jY\xb8\x9e6R\xffo@|3}" + + "I&,\\O\x9b\xc8\xe5\xe5y\xe0D\xb2G\xcfx" + + "v\x92.\xb2\xba~\x91u\xd1%\xd8\x1e\xd5jC\xc1" + + "*\x82\x90\x1c\x83au\x8fj5\x1b\xba\xe1\x19\x10=" + + "\xaa\xd5a\x1a\x19#\x18)\xda\xa3ZM)\xde\xebF" + + "?y\x99^\x8dT\xff<\xd3H\xb3\xc8\xe5\xb6\xa9\x06" + + "k\xc7;U\xab\x99\x85\x03\xedF4#\xe9%\xea\x93" + + "\xedi.\x03\x8a\xac\xec_5\xcd\xe5%C\x04/A" + + "\xec\xd2\x02\xac\xc6\xb0{\x06\xde\xa5t\x15\x05\x18\xf4#" + + "&\xf4E\x02\x9eR\x03\x81K\xab\x093\x026T\xa7" + + "\x18?\xabi\xcc\xbb\x88\xe5\xe1\xe1`m\x1bg\xa6\x91" + + "\xa7\xe8K,\x9eJ\x81Sck\x06\x03} \x16\xd1" + + "\x83\xcf\xbb0\xe8N\x87#Z\xb0\xc3\x9eZS\xd3`" + + "\xf0\xae\xae\x82)(\xf4\xa9\xd7\xd1\xf7o\xfa|\xa5m" + + "P\xf3\xbc\xc5\xb90\xe8\xde\x17\x9cZ\x08\xc4\x0d\x8a#" + + "\xa4X'\xe2\x95\xb3D\xcc\xfa\x94\x19d\\\xd17F" + + "\xe4\xe8\x98\x19d\x1bV\x8dc\xacN\xa4\xb1\xa9Iq" + + "59\x8d\xfe;\x9d\xfe;#\xccg\xf0\xbf{\xee\xe1" + + "~&\xc3\xf1Ft\xc7k\x8c\x82\xd7\xb7\xd3\xeb\xa7\x8b" + + "\x8b\x08\x93\xc4]\xed\xb1\"\xc1\xf3\x18\x91\x996\xc9\xbb" + + "4\x1d\xcd\xde\xb0i\xa4\xc3\x86\x9d\xc9%\xa8\xad\x8c\xc6" + + "d\xdd\xaa\xe9J\xa9V\xcf\xff,\xc2\xc8KqU\x10" + + "d4\xdf\xbf\xc3\xe2]a\x99\x1c\x88\x1fu\x83\x8cb" + + "\xf3\x03wX\x92n.\x07\xdf\xbc\x17\x99\xb9\xbd{\xef" + + "FR\xeb\xd2x\xf0\x96\xc7i\xc3C\xbd\xcb\x05a\xd5" + + "\xe6\xb1\x0a\xf0\xbf<:rY\xe0S\xcc#W\xe5:" + + "/\x18\xa9<\xf3\xf2\xd3w\xb0\xe8\xc8\xce\xc0gOG" + + "\xb6\xe7\xea\xb3I\xad3\xc5\xebY\x04\xa5YnA\x86" + + "\xeb\x19-e\xb0:[\xc4\xea\xbbw\x16\xc4\xe1\x85\xf8" + + "\xa5\xadb\xc0c\xe7y\xa2\xaa\x9f\x82(\xfd\xc4\xb8P" + + "!D\xd55d-\xf9\x89q\xa5\xa8\x10Uk\xc8y" + + "\xe2Ep\xa2q%\x82\xf9\x97\xe4\x05\xf3\xbb\xd6\xd2F" + + "\xc2\xfd`\xfeb/\x98\xbf3/\x98?\xec\x05\xf3\xb7" + + "\xe7\x05\xf3\x97Hn0?\xe2;\x11\xbf\x0f_[\x8e" + + "V\xeb\x89\xe6\x83\xa9\xf9\xaf\xfd\x84){\xc4\xf5\xe2\xe1" + + "n\xce]\xd2\xf9\xb0\xeeN\x0aWU\x84\x98\xdaA1" + + "\xa6^\x1b\xd1\xa1EBL\xed\xa1\xbe\xdc\x83\xf8~p" + + ">\x91\x86bj\x1fYb\xfe\x8d\x80R'\"\xf5\x11" + + "j\xffa\xc4\x9f\x00\xc9U\x11#\xfe\xaa\x097\xebj" + + ".|\xbc\x9e\x87\xb7\xd0\x9fD*\x08_\xc9d{\xba" + + "G.\x01pF>\x18p+{\x14\xe1\x06\xec\xfb+" + + "\x0b\x11\x9fD\x82\xa5\x8e\xa3\xdbm1\xcf\x83.R1" + + "\x894s\x81\xafCd\xb8\xa9\xa59\xe8\xb6\x9a\xa2D" + + "\\\xbe\xbcp\xb3>\xb1\xb0f\xf7C\xc4\xffh{\xf0" + + "\x8d\x17g\x93\xacn\x91fe\xd5\x14Dr\xcfW\xeb" + + "\xeau?x\xe1\xa6\xfc.\xbb\xf7\xf2\\\xda/\x08\xba" + + "+\xf8\xecAO\xb6.\xdd\xa9\xabZ\x8a\x8e\xad\x1f\xcb" + + "<:\xf6\xfe\x9f\\\xf5[\xba\xabI)\xec)\xa9\xde" + + "\xdf\xff\xee\xc42\xff\xae\xa6\xab>\xa6\xdb\x83\x87\xc7N" + + ",~v\xbe\x7fx< \xea{\xf0d\xf89\xbb'" + + "K]d\x90\xf2b\x03\xb8\xdf7\x88\xf8\xdd\xfe\xc2\xcb" + + "G\x05l,\xeed\x95\xd1\xec\xb8&w\xd3g\xafJ" + + "\xa8\xe3Qr\x10GKg3V\x93\xce\xda\x89d]" + + "\xaf\xc6u]\xfd\xdf(\xda\x81\xacy\xd8\xf0\xc5r\x08" + + "'+\xf7\xef\x7f\xb9(\xf4\x81\xbeg\x03SN\x80\xf3" + + "\xa5\x0b\x91\xdaiY\xde\xf5\x16\xc9K\xed\xb4,\xefz" + + "K\x08\xdc\xd4Nk\xf3R;E\x06O\xedD\xdfC" + + ",\xa6k/k\x83\xd7^\xe8S\x0b\xc8\x00>\xa5K" + + "\xfa\x9f{9\x9f\xc2\x8eA[D\xc9\x94B\xa8cV" + + "\x90\x0a\xeb\xb8K\xca\xc9\x00\xae\xf0\x92A\x95:Y*" + + "F\x92A8\x02\xf1\xf1d\xe8\x8a\xcf\x1e*c\xc9\x90" + + "\xf6\x0d\xf8!\xceu\x9eI\xd2\x86<\x83|\xa8\xa3\xab" + + "\xce\"\x15\xdc7\xc8\xcbK\x85\xae:\x87\xda\xf7\x0d\xf2" + + "a\xc5B'm\"\x15\xbc\xd1K*%\x97\x09\x9d\xb4" + + "\x95L\x02/\xa9\x14Z9\xc3)\xa7\xd4l\xd7N\xa7" + + "\xdcQ\x15\x8e\xdd\xaaQu\xcf\xbe.\x88FS\x13\xbc" + + "\x91\xdb\x9cE\x12v^\x16\x7fJd\xa8\x16\xc0j\x9f" + + "jr\x9d[\xae\xab\xc4\xf7Y\xe7\xdf\xef\xc9\x18\x16o" + + "\xd3\xec\x04\xf4\x0cH\xf8\xef\x95\x0c\x96\xf0\x1fK\x17\xab" + + "}\x0bX\x0d=\x96\xf7\xd4b\xb5o\x11\x88g\xb2:" + + "\xf8\xcfX6\xcf\xb8\xc9\x10\xbd\x07\xfc\x8eR\xda\xb9\x80" + + "\xe3\xdd/iS-\x0b\x8b\xfc2\xcdj1\xfa\xe2v" + + "^.\xa8\x1e-n\xe3+\x99\x1c<~t\x9b\xa5\x14" + + "\xa5\xfe!\xa3&\xd2V\xb2:\x9e\xec@)\xef\x9e\xcc" + + "\x15~Ia\xc4[\xe3\xdf\xbb\xe8\xca\xcf\xbc\xb8\x97\xac" + + "\xa3\xab\xb2:\xbd\xe03\x8b\x83j,\x0d\xaa>\xe0\xd3" + + "9!\xf1E\xb6\xbc\x8f\x1eTJ\xb0\xba3K\xfe\xbc" + + "\x01\x89sB_pb\x134\xa3\x9f\xf2\xc4\xfe\xba\"" + + "4\xcd\xae-\x92!~c\x91\xb3\x8d\x11_O\xf8u" + + "\x88\xdf\x84x\x8d\xe3$\xddH\xf8\x0d\x88oF|\x86" + + "\xe3%\xddT\x84\xb2\xf3&\xc4\xb7\x15\x05\xce^\xb6\x16" + + "\xa1\xfa\xb0\x19\xf1;\x8a\x02g/\xdb\xa9\x9d[\x11\xdf" + + "Y\x14\xf8r\xd5\x0e\xaa\xbf\x0d\xf1\xdd\x88\x97\x96\x8am" + + "\xbc\x8b\xf0;\x10\xbf\x07\xf1!\x8e\xc9yW\x11n\xb3" + + "\xdd\x88?\x80\xf8\xd0!N\xfe|\xc2\xefC\xfca\x0a" + + "*\x1d\xea\xe4\xcf'|?\xe2\x8f#~F\xb9\xd8\xc6" + + "\x07\xa9\xff\x8f\"\xfe\x14\xe2\x11'\xa8\xe10\xbd\xf7q" + + "\xc4\x9fF|\x9a\x13\xd4p\x84\xa2A\x9fB\xfc\xc5\"" + + "\xe7\xd6\x1fn\xef\xa3\xd4\xce\xf3\x88\xbfZ\xe4\xdc\xfa\xc3" + + "\xed}\xbc\x88B\x9b\x11\xff3\xe2E\x8e_\xea\x04\xf5" + + "\xe7m\xc4?(\x92`\xfa\xa4G%\xb1\xc1O\xd2\x8b" + + "\xff\x8c\x05\x9f`\xc1\xa8\x83\x920:?,BF\xf7" + + "A\x91\x0c\xed\xc5\x12\xc0har\x9e\xa2\xa8\xd8\xcf\xb1" + + "\xfa\x88b\x09\xa2S\xaa\x85\xc9YUL\xf9(\x8a\x91" + + "\xfd\x15K0\xbd\xfc1I\xd8\x9c#\x8b\xb1\xa3#\xb0" + + "`<>0\x16\x84\xcd9\xb6\x18;t\x16\xe2\xe7 " + + ">N\x12\xf1\x0e\x93\x08\x9f\x88\xf8\xb9\x88W\x8d\x10\xc1" + + "\xd3\xd3\x8b\x91_NC\xfc\x02\xc4\xa3#E\x1c\xc4\xf9" + + "\xc5\xc8\xa0\xceC\xbc\x11\xf1/\x8d\x16\xf1\x0e\xf5\xc5\x8f" + + "!\xffC\xbc\x0d\xf1\x89\xb3E\\Ck1\xca\x81\x8b" + + "\x11\xef@\x1c\xcet\x82\xa7i\x00-\x88_\x8ex\xd9" + + "Y\"Hz!\xe1m\x88_\x81\xf8\xf4\xb1\"\xaca" + + "1\xe1\x1d\x88_\x89\x03\x9e\xfcKI\xc45,-F" + + "Nz9\x16$\xf1\x81/\x7fC\x84/\xa84\x11W" + + "\"\x9eB|\xfc<\x11\xbd\xa0\x15\xa3\xa6\xd9\x83\xb8\x8d" + + "\x0d\x0d\x7f\\\x12a\xd2+\x8aQ\x12\xd8Xp-\x16" + + "\x9c}H\x12q\xd2\xd7\xd0\x14]\x8d\x057`Kg" + + "\x8d\x17q\xd2\xeb\x8aQ\x04\xdd\x80\xf8f|`\xd8\xaf" + + "$\x11(\xbd\xa9\x18\x89b3\x16\xdc\x81\x0fL\x90E" + + "\xa0\xf4vz\xf56\xc4w#^\x11\x12\x91\xd2\xbb\xe8" + + "\x05;\x11\xbf\x0f\xf1\xea\x09\"Rz\x0f\xe1\xf7 \xbe" + + "\x1f_\xa0\xfcZ\x12\xb1\xd2\xfb\x8a\x91*\x1e\xc0\x82G" + + "\xf1\x81\xaf)\"V\xfa\x91b\xa4\xa1\x87\x11\x7f\x02\x1f" + + "\x18\xf1\x84$\x82\xa5\x0f\x15\x93C\x09\x0b\x9e\xc6\x82\xca" + + "'\xa5J\xf8:\xd2;=\xf1\x14\x16\xbc\x88-}\xa5" + + "\xa3\x12\xceCz\xa7\xd9{\x1e\xf1W\x11?\xf3\xab\x95" + + "p>\xd2;\x91\xc5\xcb\x88\xbf\x8d\xf8\x98)\x95\xf0M" + + "T\x03\x8a\xe9\x96+\xe2\x1f >uj%\xd4!\xb9" + + "\x13\xb9\xbc\x87\xf8\xe7\xf8\xe2\xaf\xfeF\xaa\x84\x0bQ\xde" + + "\xd3l\x7f\x8e\x05%a\x09\xa2\xe7,\xacD\x8bD)" + + "\x0aS\x9cM\x18\xe5}X\x82HoS\xb7\xe1Yc" + + "j\xf0Go\x9b\xe6\x07\"\xf4v\xa8f7\xb7[X" + + "8\x90 su?e\x19\xf5\xd2gF\xfa\x1b\xb9\xf7" + + "\x19\xd4\xd5\xd9L\xdc\xe6\xbe{wuV\xcb\xfb\x9dS" + + "E\x93\xadL\xd6\xf4A@\xd5?\x94X\xc6\xcd\xe5\xf3" + + "P\x94\xc8F\xe0q\x91\\\x89\xb307\xfd\x97\xf6d" + + "\x93\x94\xc2\xd3K\xc5\x92M\xb7\xa8\xdd\xad\x16\xcb\xfbD" + + "\x86\xc8\xd3\xc3\xf2\x12\xf5\x98N.\x13\xb0\xb9\xb8\xca\x18" + + "\x8cz\x1e,)H\xa1}R\x98\x1f\xdb?sv\xdf" + + "G\x1f\x1bu\x05_\xa9\xe3\xb5\xe8m w\x81\x9f}" + + "\x85\xab\xe6\"\x8d\xf7\xb1p\x83\x9a\xfe\xbf\x18;\xa7S" + + "K\xc4\x8c\xb5\x1aIV\xc7Ss\xb5\xc0\x07k\xff\xee" + + "U\xa8\xd3\x9ahH=\xedj\x9f\xbf\xc6]\xf9k\xee" + + ",\xa7wB?\x98\x09\xf7\x7f6\xcc\xba3V[J" + + "\xd5u\xe0\xa6\xa3\x81\xf8\x9a\xca\xa06\x19577\xa5" + + "\x81\xbe\\\xd3\xbb\xdb\xe9\x1a\xb5\x17\x83\xe0\xa8\xf6\xe0\xea" + + "\xf6\xf2\x02\xbd`\xf6\xf3M\xc0<\x0b\xcc\x05{\x9d\xc0" + + "\x0e&\x07.\xfa%y\x82\xa7\xe6\x19&\x8btdM" + + "=\xff\xbaB\xab\xa1\xb3\x1a#\xef\xfb\xd0\x83%\xe1\xf4" + + "\x9a\xa8\xa1x\x95\x82\x094\xb2,\xac'g\x0c\xb4\x03" + + "\x9d\xbc\xf4@z\x147Y\xe0\xeby\x05\x11\x17\x91\xf6" + + "@b\xa4\x9cC\x93\x0d\xac.\x95\xb5\xec\xc0\x9e\xfd\xff" + + "c\xd5\x0e\xael\x0d\x92\x0bX\x84\xc3L\xf3t\xadz" + + "\xba>\xeb\x9f\x18\xbb\xa6T\x13\xe1\xdeW\xdf\xbc\x03\xe9" + + "f\xc2\xbd\x07h" + + "m)\\\xfcq\xd9\xb9\xbc\x89v\xcfA\xea\xbb\xf7\xce" + + "h\xf5Ra\xf7\x1c\xa2\xf6\xfd\xbb\xad#:\x85\xdds" + + "\x98p\xffn\xeb\xc8\x84\xb0{\x8e\x10\xfe\x84\x17\x8e>" + + "*)\xec\x9eg\x08\xf7\xef\xbc~\x89\x0b\xbb\xe7(\xe1" + + "~\x98\xfa\xe8\x99\"\xce\xfb\x18\xe1\xfe]\xd81s\x85" + + "=t\x9c\xce\x04\xfd\xf0\xf53\xc7\x09{\xe85\x1a\x97" + + "\x17\xbe\x9ew&\x18\xe9\xe7\xaa\xe99\x05\x92j\x7f\xb3" + + "\xbe\x98\xbe\xd6\xe2U\xe81\xb2\xde\x8f\xba4eM\xf1" + + "~Z\xf4\xc5d/\x1cq\xa5\x7ft\xb7\x88\xa7\xbc@" + + "\x82\x95\x94M\xd2\xfd\x09\xfd^\xad\xfe`\xad\xfe\xfcZ" + + "\xab\xbcZ\xab\x82\xb5V\xe5\xd5\xaa\xb3z;\x02\xdf\x90" + + "\xad\xb1z\x17\xb6\xd7{\x89\xea\xd5n\xee\x7f\x17\xac\xf7" + + "b\xae\xa6\xec\x9e`\xdcpP>\xc8v\xa77b[" + + "\xcd^\xea\x1d\x9d%y\xcaV\x91\xf7\x83\x87\xd5u\xab" + + "\xe9\xb4\xea\xfd\x943\xd3\xdd&\xe5\xcc\x0c\xff\xcf\x99\xfe" + + "\x9f\xe7z\x7f\xea\x81?\xbdx\xe1\xd5]&_qi" + + "6\xed\x05_\xd9\xcb\xc5\xb7\xa8\x19X\x7f\xc7\x05\xe4&" + + "eM\xa9z\xdew\x04:<\x0e7\x87\xc2d<\xaf" + + "\"\x94:\x1a\x04E\x17]\xe8E\xf3\x949\xce\xd8\xc5" + + "\x84wx\xd19%\x8e36M\xb8\x1f\x9d3\xc4q" + + "\xc6\xae <\xe5e\x98\x07\xe7\x94f\x1d\xe1\xd7\"~" + + "#9?\x9dS\x9a\xf5\x84_\x87\xf8\x1dn\xc6{\xf2" + + "\xee\x10\xeeG\xdb\x0cw\x18\xdc\x0er\xa2\xeeD\xfc>" + + "\x8a\xda\xd9!\x18\xd9\x1e\x8a?\xb8\x07\xf1\xfd\x88W:" + + "\xd1E\xfb\xc8\xcb\xf9\x00\xe2\x8f\x92s\xf5N\xc1\xc8\x1e" + + "!\xe7\xaa\x1f\x0f\xa18'2\x87\xc8y\xeb\xc7CT" + + "\xfc\x93`dG\xa8}?\x1eb\xd8N\xc1\xc8\x8e\xd2" + + "t\xfa\xf1\x10\x91\xff\x8f\xb9\xbf\x0f\x8f\xa3\xb8\xf2\xc5\xf1" + + "\xaa\xe9\x91F\xb2-\xcf\x8cf\xe4\xb7\x00c\x08$\xb6" + + "\xd7\xb0\x96l\x13\xe3\xe0\x08\xbd\x19\xcb\xd8X\xd2\xc8\x06" + + ";fCk\xa64j\xbb\xa7{\xdc\xdd#K\xac\x89" + + "\x0d\x81\xc4\xb0\xb0\x01\xc7\x10 \xf8\x06X\xc8\x02\x0b\x09" + + "\x10\xc8\x02\x17v\x81\xc0]H \x81\x04\xb2\x86\xc0\x02" + + "\x89I\x80\xc0\x0d\xecBb\x12\xa0\x7f\xcf9U\xddU" + + "3\x1a\xd9d\xf7w\x9f\xe7\xfb\x974\xe7T\xbfUW" + + "W\x9d:/\x9f\xcfM|\"{\x09\x9d\xb42\x1fB" + + "k\xe4\x93\xcdk\xf8\\2\x1f\":E\x14\xa8\xe3y" + + "0\xf1\xe1=\xcc\xc3\x98*\x0a\xd4\xd1)\xfd\x0e\xc8?" + + "\xc4<\x0cQS\xf2\x01\x9e\xff`\x98(\x11\x13E%" + + "\x14Kb\xa2\xf0q'4\x81nv\x86\x91\xf7\x08\x1d" + + "Q\xc8\x1cls\xbc\x1as?W[\xa8P\x8df\xcc" + + "ZM\xcc\x8a&N\xad&\x8e\xda\xe4P\xd5r\x82@" + + "d\x83NbjZ=\xee\xd6\xd6\x0d\x0f\x93v\x97y" + + "\xdd\xacPitm\xd0MR\x01\xc4\x1f\x9c\x1f\xec\xf8" + + "\x0a\x14\x0b\xce\xddS}v\x85\xbd\xa7\xc2Qm1o" + + "\x03\xa9\x00\xeb\xcf\xe4+\x1e\xa4\x16\x02n(\xcb\xb0\x8a" + + "m\x84\xa3o\xc7\xfd\x10\x89{*\xf0I \xa6 \x1d" + + "\xe0\xf8\xbb\x87\xc6\xdc\x90\x96LV\x97\xe5\x80QJ\xfd" + + "\xae\xff\xf5\xef?\x89\xfcd\xdf\xeb$I;wfu" + + "\xaf\xd7\x1a\xb6\x0fW\x85z\x8c\xb0\x12\xbb#4n\x0c" + + "\xda\xdbC\xf2ewTqK\x87g\xaeJv<<" + + "\x90\"\xcc\xc6\x13S\xc99\x86\xe4\x8a\xe5\x18\xaf\xc7\x1c" + + "\x82(\x1a\xac\xb4.y\xdcrL%?ru\x80/" + + "\xb9\xdd\x186\xdas\xcc4\xdbN\xc5?\x8b\xf9\x9f%" + + "\xfc\xcf\xd2S}\xe6\x8d0\xc7b\x9e\x9a\xa5\x1d\x9b," + + "Q\x19sSO\x08\x8d\xbf\xaal\xe1\xeej\x00\x11\xe8" + + "\xb2S4\xda\xbfF\xb1\xac{;\x15\xd0\xca \xb8\xaf" + + "\x82V\x06\x14\xdbaV\xb3p\x10\x1c.\xa3\xf6\xd0\x90" + + "\xb95\xb8y\x83g\x8a1\xcb\xab\xba\xf16q\xe3\x9b" + + "\x95\x1b\xdfx\x8c0\xc8\xd5he\x9b\xac\x7f\x15\xc5\xbf" + + "\x95\x99$1W\x92\x07\x07\xf95\x955/\x87\x81\x90" + + "Tb\x11\x88}\x1b\xe4\xdeU\xb2\xd9\x08$\xb2J\x88" + + "\x1c\x9e\x97\x9a\xbc\xf4\x1cB\xfa/\xe1\xc07H|\x12" + + "#$y\xd3\x1e\xb5\xf4\x94g\x80&\xef\xdc\"\xc13" + + "\xe3\x85\x9c7&=\x14\x1cx\xb5\x93\x96\x0d3\x0f\x1f" + + "\x06\x96u\x9b\x9d\x99G\x9e\x9b=\xffcIY\x89\xad" + + "\xb2\xa4\x9d\xf3#\xc9/\xe0\xa9_~\xed\xe6o|\xbe" + + "?\xa4\xb8\x0e\x00,i\x00\xe7Ju\x9a\xf0oj\xf9" + + "\xc3\x8d\xd9\xb3\xfe|mp>\xc3v;\xe1\x82\x04\x01" + + "Ei\xc2\xdf\xb5\xfe\xdb\x9f\x9e\xf7\xf9/?\x7fh\xac" + + "\\\x85\xc8>sB\xf0\x05\x09\xe8\xcds\xf0\x0bZ\xcf" + + "\xc16\xfbo\xc5o\xa6\xff\x05\xfcf\xd6\xbf\x80`\x9b" + + "\x1b\xcf\xc7\xafk\xfd\x10~]\xfd\xe7\x10\xe2\x0f\x19\x85" + + "N{l\x8dM\xda]\xd7d\xae\xeb\x0f\x97MsU" + + "\xcf\x86.\x12*W\xf5\xd0\x0d]*\xe9Y\xf0\x84\x11" + + "x\xc2Um'.Q\xd9\xa9\xe0\xf85\xb6\xebF\xe0" + + "l]\xa6Q\xaaP:\xb6\xe5u\xf7\xf4E\x82\x8fj" + + "\x1b\xe7\xcaZ\x15k;q\x89o\x1a\xa3\xcc\xf5\x1cF" + + "\xda\xf5\"\x9cv\x92\\\xa4jj\xf7.Q\x97u\xc2" + + "\x1a\x96CGN\x97\xad\xe5\xd9DLR\x8e\x05\xb5\x96" + + "W\xa9\xf4\xf2n\xea\x19\xc0n\xc2\xd2\x95\xfa\xe4\x8a\xd5" + + "\xd8M'\xad&d\xa7es~*\xd7+\x0f\x0f\xf7" + + "8\x0e\xd1l\xc7\x1f\xb6\x9d\"rKP\xc7\xd7s[" + + "C:\xc3!\xc3k\x0d\xe4C\x86\xb7(\xf8?\xe7\xe4" + + "\xc26\x96\xcd!t\xd5\xc9H\x9b,\x1c\x1f3l\xab" + + "?A\xa9\xff\xfcI7>t\xd1\x8c\xa7n$\xc9\xd9" + + "\x0b$lP\xb2e\xc0\x1f\xbe\xf6\xe9\x91\x9b\xa6X?" + + " \xc9\x96s\xfc\x9e)\xbf2\xe7\xac~\xeb\xfb$\xd9" + + "\xb2:\xbeF\xb7\x98\x1f \xf5\x12j\xf9A`\x9f\xb4" + + "\x1b^\xd6(X\xfe\xda\x80\xbf\x0a\xb1N%9\xf6\x0d" + + "\x155\x01\xc1\x06\xd7\xc0\x1a\x85\x90[AL\x10\xa92" + + "&\xba\xc8\xdc\x9d \xe9\xfc@\x10\x86" + + "\xe1/\xfd\xf8\x95G\x7f\xf0\xe3\x17\x10\x84\xe1\xcc\x8d\x9b" + + "p\x85&\xed\xdc\xee\xf0W\x1a\xa6\xc7\x1c\xc1i\xac\xd6" + + "8*\x1c\xcd\xe1j\xfd\xfe9*\x19\x8bX\xae?\xba" + + "F-f\x0c|M\x8d\xf8\xe9\x86\xd5H\xb0\x98F)" + + "M\xb5\xe0'!\xb9\xc5\xf1S\xa44u$\xba[%" + + "\xb78~\x8a\x94\xa6\x8eC\xb9\xe4\x16\x0f\xaa\x8b\x8e\xc7" + + "OzQX\xbd\x14\x135\x8e'a\xfb\xd0/,\x91" + + "\x0b\xdb\x0d\xdb:\x1d9\xa1\xc3\xce\xa9.\xc6i\xe7\xc6" + + "b\x8d&\x01|\"EB\x1b6jh\xb5\x9bY\x85" + + "\xb2\xa9;\x1b\xa88cwf\xb2\x13\x1aV\xa9\xec\xb9" + + "\xebNS\x87\xb00\xef\xd7\x11z\x9a\x1c\xd6|\xcd\xaf" + + "\x90!I\xf5J\xc3\xa4\xf8\xde\xb8y\x9e\x90oY\xa9" + + " \x0aP \x0f]\x9d0\xb9%:\x18\x1b\xaf\x806" + + "<\xa6\xa2j\xf1V\x9eX\xbb\x80\x90\x98\xa5\x8f\xfa\x96" + + "\xee\xea\xebM\xcf!\xed\xfa\x80^2\xf2\x01\x8b~/" + + "\xd5s \xd7\x07\xe2 \x8eo\xcb\xd9\xc5\xc3n#z" + + "m\x0b1k\xd0\xf6=\"\x1c\x94\xf7\xac\x16\x88\x1d\x0f" + + ")\x83\xf2\xc1c$\xady8(\x1f\x06\x83\xf8\x01\x8e" + + ")\x1b \x83<6\xc0!e\xfb_\x91\xa4A\xc9\x97" + + "V\x0b\x1e\x0dd\x9b\x9a\xcbM\xbe\xf7\x87\x94q^\x7f" + + "47\xf9>:_\xa9\xe5\xad\xf0\xd5\x04\xfb\x13\xaf\x06" + + "\x80H\xe0\xa21l\xcb\xee0K#\x84\xeaU\xa6+" + + "\xaa:\x19\x121T\xabF\xf0\x1a\xd5\x9bC8\xa0\xcb" + + "f\xc3t\xd8\xad\"\xc2\xab=9\x9c\xb9qSf0" + + "\x80\x00Rz\xb3YX\xa6O*\xbd\xf9D\xb3\xd2I" + + "Ao\xbe\xd4,\x18H\xdeSH,\xdem\xae&\x16" + + "\x89bm\xf3\x82\x0a\x12\xa6\x90\xfafA\xf0\xdd/R" + + "k\x98\x8fG\xf9\xbc\xe0{\xa5cU\xdbtZ\xbdo" + + "\xa7\xe7T\x0b\xaa\xd9\x86\xe2cY\xaf\x9a\xf0(>^" + + "Cv\xceD\xd9d\xc0\xbc2\xee@H\xff\x11\x94\xfa" + + "\x8b\xef\xbf8\xf3\xe6o\xff\xe3\xefH\xb2\xf5V\xffw" + + ";\x7f\xf2\xf4\x9c\xddW\xfd\x82$\x97n\xf2\x1f\xfc\xd3" + + "\xe6\xbb\xbf\xbf%\xff\x0cI.]\xed?{\xc4w~" + + "\xf6\xfc\xa9m\xb7b\xdd\xe8q\x97\xbe\xf8\xc0K7M" + + "\xf9*I.\xbd\xd5_\xb7\xbbpB\xe9\xa1/\xfc\x99" + + "$OZ\xe0_\xd03\xba\xe9\xfb\x0f<\xbd\x97$\x97" + + ".\x0fy9\xe8\x866\xd5\xf6\x0d\xa3o\xda\x86\xc5~" + + "\x10\xfc\x00\x93.\xa8\x8a\xd7\x82\xb2x\x0cQ\xf0\x08\x05" + + "\xcb\x1b9/n\xd8\x96\x1b\x87\xc5\xa1\x9dS\xefUT" + + "\xf2tVT\xf2\x04yRwb\xfa\x9f\xac\xe4\xd1\"" + + "A%\x8fSQ\xc9\x13\x8d\x04\x95<`\xa2<\x04\xf2" + + "'#\x1c\xdc\x04F\xc3\x13x\x9a\xc7A\xfclPh" + + "\x03\xc3\xe1\x19t\\=\x0d\xf2\x17\xd1\xb1',\xaf\xe7" + + "\xb1\xfd~\x90\x1f@\x07\x9e\xb0\xbc^E\x07\x98tP" + + "5\x09\xcbKqPE\x83\x8a\x9aFt89\x84\x0c" + + "h0\x0a\xd1\x91\x1f$G\xa2\x93y\x16\xc8\x97\xa0\x93" + + "\\\x04\x16Z\x11\x0beQXP\x93\x12\x81\x85^t" + + "\xc2w\x83\xbc\x0f\x03\x05\"\xb0\xb0\x16\x0bd\xd6\x80|" + + "\x04\x03\x02\"\xb0\xc0P\x9e\x07\xf9\xae \x90\x82\xd5~" + + "\x08\x00)\x03,\xf5S\xb9?\xee\"\xed\x1c5\x90B" + + "gQ\xea\x7f|\xed\xf8\xe5\xc61_y\x85\xa4.\xc7" + + "@A\xf34\x1eT8\x17\x1d\xe7ca\xd0eZ\x13" + + "O\xa8\xba\x1c\xaf)\x83+4\xc6\x03\x0bW\xa3\\\x06" + + "Q\xd2I\xee\xbb\xbb\x1e\x8b\x81d\xb0dF\x1c}t" + + "\x8bo\xd1\xa6\xd0\x8ahFK\x82G\x04\x14\x80\x9aG" + + "\xb5\x08m\x8d\xc1T\xf1)\x0c9\x1c\xa3\x86\x1c&\xe4" + + "\x10\xe3\xef\x0e\xdcwT\xca\xba\x1d\x9bdJH\xd1\xa3" + + "Z\x845\xf2\x8d\xc3JZ\\\xe3v}\xb7\xee\xb9\xcc" + + "w\x7f\xfc\xc3\xc9`\x89\xab\xf5\xe1\xca~\xc8\xa3\xa9a" + + "[\xe8\xe5\xaa\xd1\xc6\x14\x14@D-\xb3U\x1bMW" + + "\x1be\xfa\x1c{\xc8\xadE\xf4\xd9\x93/\x1c\xe6\x1cL" + + "\xcf\xbb\xdd=}4\xd8\x9f\xca\xa6\xe1T\xc3\x9b\xc6\x8b" + + "\xcc\x83}}8\xcfT\xdfj<\xeb\xe5'\xbf\x89\x9a" + + "ZtY\xf6\x8c1\x9a+Co\xf3\xdc\x1a\xc5\x1d\x88" + + "\x13\x09i\xc7\xc9\xc3\x0d\x13\xbf'P\xf9\xb8\x1b\x16\xcb" + + "\xdb\x0e'E\xf1\x84\x13 \xa8\xab\xfbZ\x0c\x9f\x1e\x12" + + "Gn\x900\xa4 \xa67\xa2!\x94t8\xa3VR" + + "H\xf5i\xa6nY\xcc\xc9\xda&>\x82\xe2>\x83\xf7" + + "\xfa\xf1mw\x7f\xe7\xa6\xb7~tA\x80L\xad\xe7\xc4" + + "M\x843/W\xc4\x86\x8c\xc2a\x9cH\xa7\xeb\xa3\x88" + + "-wB\x00%\x17\xe0\x83(^\xcd\xd5\xb5\xe8=\x06" + + "d]'\xdc\xb5\xe1\x95\xf3j\xa9MH\x8dV\xe1\xb9" + + "\xad\xb9\x1c\xad\xb3\xf0u\x8eb\xc9'\xbaY\xb5?o" + + "\xcf,\xb8\xfa\xdd\xcbI\x92\x0e\xf8\xa88\x1dL?\xa4" + + "\xaa\x133\xfdq\xb8\xd2b\xbd\xffB\xb5\x10f>f" + + "LH\x0b;(\x849\x1e\x13&$+\x9d\xd6\xccg" + + "\xfaV\x94/\x04\xf92\\\xf8S|\xaa_\x8aU&" + + "\x0a[]\x9aO\xf5+P\xae\xe0\x09\xb4\xf0\xa9\xbe\x07" + + "-x\x05O`\x06\x9f\xea\xab\x12/\x92\x0d3\xf9T" + + "\xbf\x11\xe5\x12O`\xca,>\xd5\xeb\xb8)\x97\xe0\xed" + + "\x8d\xb3\xf9\\_\xc4D\xfb\xd0w\xc0\xab\x9e\xe3\xb2\xa7" + + "\x04a!O\x12\x0b\xcb\x09-\x1b\xa1\x0b\xc3\xdf\xdbu" + + "\x07w\xae\x12\x82\x11\xf9\xbdu\x12S\x8e\xf2]{\xd8" + + "\x9b(5\x8aE\x967t\x8f2\xd0\x0d\x99\x15\xc98" + + "\x0e\x87H\xaa\xf0\xef\x0b\x82rBeV\x87=\xcax" + + "\xb2ZP\xf6\x167,\xdd\xac\xa1\xe6\x9f\xc1\xe1\xd0t" + + "jpsVD\xe4\x94\xda\x92M\")b\x87\xf4\xcc" + + "\x8f\x0f(\xee\xd1HD\xb8G\x87\x04\x81\xed\xb5\xc26" + + "\x04[\xf9jG\xa0\xf5\xdd\x8d\xe4\x0dNi\xad\xee9" + + "D3\xc6\x0e\xc5&\x19\x14z\x86\xedc\xc6X[\xf5" + + "\x01\xa12c\x8cu\x1a\x85\xc9\xec\xb7\xca\xc7\xeec\x8e" + + "Q\x1a\x81\x0eRr\xc6\x95\\\xf4z\xbe\x17h\xda\xa2" + + "0k\x95\xdd!\x0e\xe2\xc4\xd3\xe6\xe3\xfe\xf6\xab\x16~" + + "\xff+Kw\xdfL\x0eY\xc5\xd3e\xda\xb1\xdc\xd6 " + + "\x1b\x06\x81\xc5/\x9b}\xd4\xad\x1f,\xfb\xbb+Hr" + + "\xfe&\x12\x09\x98\xd3[\x1c\xc1\xad5\xb7\xba\xcca2" + + "\xb2\x8bC1\xeb\xe0smh;\x01\x7fe\x9c\xc0\xd8" + + "W]l\xe7\x07\xe9Ic\xaa\x8b\xad\x8c\xb0\x1ec\x01" + + "1A\x98Cr9\xfa\x9c.\x0b}`\xc1\xbe\xfe\x16" + + "<\x0f\xd2\xcb<\x1a\xec\xeb\xc1\x16\xc0}\xbdd\x91\x09" + + "\\lO\xe0\xd7/]`\x81\x8b\xed\x19<\xbdt\x81" + + "\x05.\xb6\xe7\xd1\xf5&]`\x81\x8b\xedUt\x8d\xa1" + + "\x0b\xec-\xaa\xa4\x90\xbc\x81r\xc9\xa0>\x8dR\xff\x8d" + + "M\xe7\xa7\xae\xfc\xf67^ \xa9w1\x97lJ," + + "`\xa8\x19\xa8(\xe1\x99\xda\x100\xd4T\xb0\xb3c\x99" + + "\xc9:\xc7\xc0$:\x8e\x9b^5\xc8\xaa\x1bd\xb5\x89" + + "\x1b\x09h\xd3g\xbb\x86X\xee&\xd1\xa2C\x01\xb9\x0b" + + "k5\xa8\xe2\xfd3\xd9\xb0\xd73\xce\xfaHL\x0d\xf8" + + "!\xcdY\xcf8#\xf1\x8a8 4\xee4\x0d\x8bd" + + "\xb6\xf6Mh\xdei\x1a\xa4\xdd\xaaT\xb8e\xab\x80\xdb" + + "\x87v\xe6V(*\xc6fi\xc4\xb6X\x15\xf7\xa0k" + + "2V\x9a\x84\x8f\xf00\xfcX}v\xbb9\xde\xa7{" + + "#U\xa1\"\xa7\x16\xd8\x90#q\x85\xc2\x9di\xd9\x11" + + "El\x97E\xa8?\x86e\xc7F\x8ed\x0cV\x838" + + "r\xfc\xd0\xeas\x0e\xad>\x0c^\x02r\x84c\xe8\x93" + + "s\xe3\xa8\xa5(\x03\x15%'\xc1\x97wi\xdd\xf2\x8a" + + "\x92\x93\xa0\xd2\xecr,\x9d\x90%'\x02\xecuB\xc9" + + "IT$7\xec\xc3\x12\x0cYBR'\x92\x1bnA" + + "\xc0oYBR/\x92\x1b\xee\xc4R\x0eYB\"\xd8" + + "\xb4S\xf7\xd5=\x02\xe6<\xc8\x1f\xafS`\xc3\x1eC" + + "@qY*\xd2\xa8\xf1O\xef)\x94\xcbR\x91)i" + + "\xbe\xf0V\x97\x8aL\x8d\xf2M\xd6KX\xe0\xf1\"\xc8" + + "_\x0fJZ`\x93\xf5\x1a>\xef\x01\x90\xbf\x03\xf2&" + + "N\x1b\x99z\xbb\xee~B\xb2\xef\x80\xfc\xc3:Qi" + + "\x06\x9f\xeb\x07u7\x04%!\x0d\xf5\xb0)\x13\xa4(" + + "u\x98\x9a\x1f\xad\xd7h6\x81\xd5\x05\xa2t\xa5\xa9\xfe" + + "W\x84d\xd3 \x9f[/`\xe1\x93\x84\xa4\x8e\xc4*" + + "\x05Y\x11\xd2\xdc\xcc7Z\xf3\xb1\xd2\xe2X\x90/\xaa" + + "W\xd0\x12\x8e\xc7\xf3/\x04\xf9\xb2z\x05-a)\x96" + + "\x0a,\x01\xf9)\xf5\x0aZ\xc2\x0a\xac\x089\x05\xe4k" + + "@>\xe33<\xa9\xa2\x17K\x02dE\xc8\xcc9|" + + "cV]\x112k:O\xaaX\x8f\xd7\x0d+?\x92" + + "\xb3\xf9\x86-u\x16^w3\xc8G@>G\xec\xd7" + + "\x18^7,\xf0H~\xea\xb3|\xbb\xb6\x0d\xaf[\x02" + + "\xf9\x0e\x90\x1f\x91\xe4\x08\x9e\xe3\xd8\x0f\xb2\xbc\xe3\xc8f" + + "\x9e\xd9ua\xfd\xcf\x08\xc9^\x02\xf2\xab\xb0\x04\xe2D" + + "\x9e\xd9u\x05\xde\x8f\xac\xee\xc8|\x8egv\xed\xc3\xf3" + + "\xcb\xea\x8e\xb9kxf\xd7Mx\x9e\xb0\x8a#y\xf4" + + "Z\x0e\xe0y\x0f\x96L\xdc\x0b\xf2G\xb1\"'\x8d\x15" + + "0\x8b\x1f\xae\xc7\x8d\xa8\xac\xc9\xf8t\x0b\x96\xc0,~" + + "\xae~\x08\x14\x07@\xf1\x0e\x96\xb4\xcc\xe0%0o\xd7" + + "\xbfIH\xf6\xbdz\x8d\x0e\xc4\"4y\xdcLD\xf6" + + "\\\xfcQ}'\xb4o\x88i4\x9b\x06\xc5gf\xf1" + + "\xd2\x98d\x0c\xda\xcf\x02\xf9\xb1 \xff\xecl,\x8dY" + + "|t\x0c\x0fX\x08\x8ae\xa0\x987\x87\x97\xc6,\xc5" + + "\x03N\x06\xf9*\x90\xcf\xff\x14V\xc6,\xee\xe1\x07\xf4" + + "\x81b3(\x16\x1c\xc1Kc6\xe2\x01g\x83\xdc\x04" + + "\xf9_\x1d\x89\x951\x8b\x0d~\x80\x07\x8a]X\xf6q" + + "\x14/\x8d9\x17\x0f\xb8\x00\xe4\x97\x81\xfc\xf8\x0c\x96\xc6" + + ",\xbe\x94\x1fp\x15(n\x04\xc5\x09\xf5\xbc6\xe6\xfa" + + "\x18n\xe3A~\x1b\xc8\xffz./\x8d\xb9%\x06_" + + "\xd9\xcd \xbf\x1b\xe4\x8b\x8e\xe6\xa51w\xc6`\xc1\xbd" + + "\x03\xe4\x0f\x80\xbc\xf5\x18^\x19s\x1f\xd6\x9b\xdc\x0b\xf2" + + "GA\xde\xf6iN#\xf00\xca\x1f\x02\xf9\x93\xb1\x08" + + "\xa2b\xac\xec\xb2\xcb\xaaq\xda>\\Y\xff7\xa2\xbb" + + "\xa7\x96\xdc3\x18\xd1\xd8\xd6\xd0\x80\xae\x06R\xe6\x8d\xd6" + + "\x1a\xd44\x0d\xcc\xcc\xd3\xf2nh\xb4\x16@c\x9a\x06" + + "\xe59{\xae\xf4\x1b\x88\xbc\x84N\x12S\x0b#\x0a%" + + "\x17\xe7\xdd\x08\xe8\x02\x0c\x0d\xcb\x1b'\x13Z\x90v\x9e" + + "V\x11\xe6\xd5\xc1}\x98\xb6\xa5\x93v\xd7\xdd\xc8\x94\x8c" + + "h\xe1\xb6\xdeHb \x9d\xd0<\xe3\xba\xdd\xfaxu" + + "\xebnD\xd4P\x9f\x11\xe4\xd4\xe5\x8f\xe3\xb6\xf3\xc7\xa9" + + ">j-5D/ \xaat\xf8\xac\\;H\xe1\x81" + + "\x0d]\xa9\x10\x11\x9a\xae\x08<\x92\xfa\xcc\x15\xb8!A" + + "+\x0a\xad\xe0\xb15\xf9\xdc;\x87\xf2\x95\xefc(?" + + "Y\x97\x0f\xe5ku\xf9P\xfep]\x1e\xb4\xa8\xee\xf2" + + "\x9d\x05\xdd\xac\xb8tA7'{\xdb\xbaY\xebm\xeb" + + "\xe6\xe1\xde\xb6h1\xe1m\xe7@\xba\xd2a\x14\xa1e" + + "\xc6;\x0dM9o\xa0\x8cp\xa5<\xb3\xc4]\x09Q" + + "i\xe8\xb8\x00\xe4\x0bO](\xb9k\x98^\xca\x92\xe0" + + "%W+\"\\^q\xda\xea6\x94\xb7\x11X&\xaa" + + "z\xd0>\xd5\xb45\x1c\x0fb8\xac\x0d\x06\x0d\xb2\xd1" + + "\xa9#\x1d\xdbF'k[{\xac\xc0Q\x9dy7R" + + "}D\x1c\x9f\xa5\xbaY\xf4P'\xae\x1e\x05x;\x87" + + "9q\xd0\xec\x93\x9f\x98?\xa7n~\x92;>U7" + + "\xff\x82\x13\xeb\xe6'\xb9\xe3\xa0\xd9_x\xe2O\xd0\xc7" + + "\xa2\xd9'?\xf1\x88\xee\x0ex9Q\xf5\x16\xfa\"\xc6" + + "]\x8f\x15\x07<\x92\xc9\x0d*\x80\xcb>\x9f\xac\xd7\x0d" + + "\x938V\xab\x07b\xb3T\x1c\xf0r\x01\x91d\xe8t" + + "\xe3\xd6\xacKb\xcc\x9b\x98\xdd{x\x9f\x82B$[" + + "\x93\x16\xad\x93#\x9e:\x08\x87\xc3I\xde\x08Vp\xf8" + + "9q&t*\x1a\x1c\xfb\xd9\x87\xfd\x07\xb6\xc9\xe8\x9e" + + "a\x15&c\xdb\x0f\xc9\xa2\x15\xaa\x85\x8a\xc8\xa5\xc3#" + + "\x97\xd7\xf0\xc8\xe5\x0d\x84\xc4\xec\xe1a\xbf\xe40<\x94" + + "d\xf0\xe0*\xee]\xc734\xab\xa0\x0aW\x1a\x96\xe1" + + "\x8e\xc4\xd4\x1b\x89N\x96'\x14 \xeaS\xbc\x1b\x13\x0d" + + "\xfc\x15\x14a\xb8S+\xe8\xfdp?\xa9\x15t\x0f\xdc" + + "\x90\xf8\x1b\x15\x7f\xeb\xc4\xdf\xfa\xd4\x0a\xfa&!4\x96" + + "\xea\xa0\x8f\x10B\x1bR\x1d\xf4\x06Bhc\xaa\x03\xb6" + + "\xeet\x8a\xf8;U\xfc\x9d&\xfe6\x89\xbf\xd3S\x1d" + + "\xf4VBh<\xd5\x81\xd7M\xa4:\xf0\xbcI\xf1\xb7" + + "Y\xfcM\xa5:\xf0~\xd2\xa9\x0e\xfa#BhK\xaa" + + "\x07\xe53\xc4\xdf\x99\xdccGgq$P:[\xfc" + + "\x9e\x93\xea\xa1w\x11\xe2;\xcc\xd4\xc7\xd7\xea&\x1d." + + "[\x82\xa8\xdb/[e\x97\xe5{-\xca\xd1\xb3\xbdU" + + "\xed\xba\x957Y>\xc4\xd3\xa6\xde\x80\xee\xb1.\xdd\xa2" + + "\xad5dm5d\x8b\xabd\x83z\x8e\x8e\x84\xb2\x08" + + "\xcaN-\x9a\xba\xa5\xc6\xce\x02u\x14\xd5\xbd\xe2\x97\xe7" + + "\x92@\x81\xf2l\xc9\x88u\x17\xf5\xaa\x0bdK\x86\xd6" + + "\xe5V\x09\xd7\xeb\x8e\xe6\xb5\xd6\x12\xb6\xd5\x12.\xae%" + + "\\:Q\x18\xf7&^\x7f\xbd;DH\xf5C\x1b\xc5" + + "\x09\x1d\x06\xb2\xc5\xbe\xc3\x0a\x06V\x04v\x1b\xa3\xcc)" + + "0\x8bzU\xedN3\x8dv\x8b\xf5Z\x86W\xd5k" + + "]\x81\xb9\x90c5.\x98\xa3[\xabd=c\x1e5" + + "&v\xd6\x84c\xf1a?\xe7\xbb\x86\xc3\xac\xaa\xf1\x11" + + "\x00\xb5So\x8dm\x97\xce\xd0\xbdLn$oO\xf6" + + "Y\x0d\x0a\xf0\x19\xf3\x84\x10\x0eG\x01\x00\xef\xac\xa0\x82" + + "_-\xc9\xbd\xe3[J\xac\xe0oe\xe3\x18`\x98<" + + "\x09Nq\x12\xd6bO\x1c\x90\x0c\xb7\xa1K\xe2\xc2N" + + "\xe1\xfb\xbcDqI\\\xd4\xa9\xe4\x8b\x06L-\x97\x0e" + + "\x89|\xd1\xab\x04A\xee?\xbf\xfb\xfe\xae\xd8\xbd\x7f|" + + "\x9c$\xaf\xd8D\"\x87F\xeb?,\xc3@@\xc5E" + + "b\x03%\x09C_\x93\xb0\xb0\xfe\x13 S*\xb3\xb9" + + "d\xa2U\xc2\x1b{$MP\xd8\x15K\x97+\xe1\x8d" + + "`\x12\xa7,\xcfq'iH\xd6\xd5nW\xa2\xa5L" + + "\xc6\x84k\xe9\x05\xee\xd5\xa4\x9c\xc5\xe7M\xe3\x82\xd2\xcf" + + "\x06\xaf\xf9*I\xd2-\xbe\x80\xab\xe6$O\x15<>" + + "\x03\x0a\x8f\x8f@\xff\xac\x0c\xbc\x85\xe79$F.\xcf" + + "v\x0d3P\x14n\x9acTn\x1a\xf1\xec\xfb\x16\xa8" + + "\xdc4b\x18\\\xbf\\Rc\x06\x19(7]\xa3&" + + "\x08GjQ\xeek\x82\x9bf\xb9\xcc\x1a\x8e\x19\xf91" + + "\x9a\xf0?\\:s\xf0\xd7{\x7f~Q@\xba\xaa\x12" + + "4\xb5\x8f0=\xcf\x9c04W\xb6\x8c1\\\xfd]" + + "O/\x96N\xd7-M\xfa\x913\xdb\x8d\xbc\x172\x97" + + "\xb5\x8f0\xe4B=t\x05O\x0dP\xf3\xf8&\xdbb" + + "\x9f\x80Sj\x81\x8c\x85U \xcf\xc6=V,\x1d\xc6" + + "_\xb8\x12\xa3\xc5\x15\x19\xdb4\xdf\xbfH\x8b&\x04," + + "[\x07\xba\x97eU/\xad\xe7\xbe\xaf^\xcc\xb0\x94\xc1" + + "\xa5\xc8\xf4\xda\xc1%M\x00\x7fn\xc4 RX\xbc\x8b" + + "\x050\x08\x03\x8c\xc1.\x99\x98Z'|V\x06\xcae" + + "\xd0\xa9^T\x0d\x17Q\x1e2\x06c\x01\xcct$\x0c" + + "\x1eR\x09\x83\x93\x0d\x1a\xf7M\x8d\xa3\xdb\\z\xdf\x1b" + + "\xa3\xdc7\xa5\x90\x02\xdf\x16d\x8e6W\x92\xbb?\x8a" + + ".\xec8\xf7M=\x8c\xee\xf4\xd0\xfd\xcec\xa9k\x98" + + "Eb\x05o$L\xe2/\x98\xf6\x90n\x9e\xaa#\xa2" + + "C \xc4\xa6\xe1\xcc\xf3\xd17^=\xf3\xc2\xa6\x9d\xff" + + "\x10\xe6G\xf2\xec\xf3.\xaa\x97\xb0\x1a\x84\xc5\xdd\xb2\xe9" + + "\xd1\x84\xbfj\xee\x91\x8f\xde\xff\xfb\x1f>\x10\xf0\x1c\x99" + + "\xccr\xfb\xec\x10\xac\x17\x7fg\xf50\xe5\x13\x7f\xf78" + + "\x8e\xe2\x9f\xb6\xdcA\xa7\xccH\x0c\x8e\x0a\xb7Yv\xae" + + "\xecn@t\xfb\xe0\x93\xd5\x02\x8f8\xa8\xbal\x8b\xd0" + + "\x10X\xb2> \xa7\x1b\xd1\x9d\x92\xc5\\\xd2\xeefs" + + "\xb6\x13\x96\x0b\xc4\x82\xe07\xcb\xd9\xa3\xcc\x11\xd3\xc5\x84" + + "\x9a\x86\xe8\xe1j\x8c)\xc6R\xe6\x86\xe3\xfc\x19\x98\xcc" + + "\x9f\xd6h\xff\x8br\x9c?\x7f\xb1\xcc#\xa31J\xfd" + + "\xdd;:\xe2?\xbe\xf3\x87\xf7\x91\xe4\xfb\x9bH\x04\xbd" + + "\xbb\xf0a\xbf\x0a\xc7\xbe\"h\"4\x1e\x0dI~p" + + "\xabJ\x13\x11\xdd\xc5\x07k\x1d\x86f$\xd0{]#" + + "w\xc8&1\x04#\xf9\x1d\xea\xa7\xf0A<\x1b\xb3\xa8" + + "\xc3\x1cJ\x81\xb1\x90\xaf\x8a\x17ph\x81>\x87bn" + + "\x10\xae\xc3\x87d\xba\xe5\xedE\x82\xe8\x84\x96\"\xd5\x88" + + "V\xe4\x1a\xd1\x84\xccu\x12\xc1\xfd\x11\xdd\xc9w:\xfa" + + "\xd6\xb0\xa1\xa6\x00sT\x1a\xdc\x1e#4\xee\xff\xec\xe7" + + "w\xfd\xf1\xb4=\x9f{J\xc6\xf9\xc36<\xc1\x1cs" + + ">\xe2\xfeh\xb2\xf0\xf1\xc3\x0fM\xddw\xe8\xa8\\\xcf" + + "(\xd3\xb0\x1e%\x9b\x8f\xc8\xdc\xa7\x04V\xe7%4\x9a" + + "\xbd7\x11\xa1M\x11\xdf\xe7\x9e\xf9{\x12\xf0U\xde\x0d" + + "\x8a\x87@1\xffc\x9f\xbb\xe6\x1fL\xdc\x05\x9f\x19(" + + "\x9e\x04\xc5\x9e\x8f|>\x0f=\x91\xd8CH\xf6IP" + + "\xec\x07\x85\xf1\xa1`)\x7f\x0e\x8f\xd8\x0f\x8a\x03\x89\x80" + + "B\x1cf\xa8W\x13\xc7\x10\x92}\x11\x14\x07Aq\xd2" + + "\x9f\x04K\xf9\xfbxW\xef%4:\x90\x8c\xd0\xa6\xfa" + + "\x0f\x04I\xf9G\x09$f\x82\x03\x1a@\xb1\xe5\xa0/" + + "\x10\xe2\x92\xf0\xda\x1b\x92\x1a\xcd\x1e\x0b\x8a\xa1?\x0a\x96" + + "\xf2\xa3\x93m0\x1e@1\x0f\x14\xe7\xff\xc1\xe7\x1e\xfa" + + "\xe3\x920\xb0\xe6\x81b\x09(\xbe\xf6\xbe\xa0/oM" + + "\xdeOHv\x09(\xfa@q\xe1{\x82\xbe|m\x12" + + "\xe6\xc7>Pl\x06E\xfc\xbf|>\xe1mL\xc2D" + + "{&(\xf2\xa0\x18\xf9O\x9f\xcfxz\xf2b\x98!" + + "AQ\x02\xc5\xc2w}\xee\xa6/\xe2\xed\x96@\xb1\x03" + + "\x14\x97\xbc\xe3\x8b\xb9\x10\xaf\xb1\x03\x14W\x81\"\xf9{" + + "_`\x9f'aR\xbd\x0c\x14\xb7\x81\xe2\xf3\xff\xd7\x17" + + "\xb3!^\xfcfP\xdc\x0d\x8a\xe6\xb7}>\x1d\xde\x99" + + "\x84/\xe4\x0eP<\x00\x8a\xa5o\xf9\xdcW\x7f\x1f>" + + "\xf9\x03\xa0x\x1c\x14G\xfc\xce\xe7\xce\xfa\xc7\x92\xd0\xeb" + + "\x8f\x82\xe2iP\xa4\xde\xf4\xb9\xb7\xfe\xa9$\x02b\x81" + + "b?(\xd2o\xf8\xdc]\xff\x1c^\xfcYP\xbc\x02" + + "\x8a\x19\xaf\xfb\xdc_\xff\x12>\xf9+\xa0x\x0b\x14[" + + "\x7f\xebs\x87\xfd\x1b\xd8\xbbo\x81\xe2 (\xcc\xdf\xf8" + + "\xdcc\xff>*\x0e\x82\"\xdd\x1c\xa1M\xe7\xbc\xe6s" + + "\x97}\xb2\x19\xfa*\xdd\xac\xd1\xec\\P\x14\x0f\xf8\xdc" + + "g\x7fd3\xc6.@q2(\xac_\xfb\xdci\x7f" + + "\x12*N\x06\xc5\x99\xa0\xf0~\xe5s\xaf\xfd\xfaf\x18" + + "\x88g\x82\"\x0f\x8a9\xaf\xfa\xdcm\xaf7\xc3\x03\x9e" + + "\x0d\x0a\x13\x14\xe5W|\xee\xb77\xf0T&(\xc6@" + + "\xf1\xb9\x97}\xee\xb8/7#\x97\x1b(v\x80b\xd6" + + "\x7f\xf8\x1c\xbbj\xbc\x19q\x07@q\x01(\x96\xbd\xe4" + + "s\xf0\xaa\xf3\x9a\x11T\x15\x14\xbbA\x91\x7f\xd1\xe7\x9e" + + "\xfb\x0b\x9b\x11B\x0a\x14{A\xc1~\xe9sV\xae\xcb" + + "\x9b\xff\x93\x90\xecU\xa0\xb8\x11\x14\xa3/\xf8\x82\xfc\x17" + + "\xbb\xe4FP\xdc\x01\x8a\xd9\xcf\xfb\x1c\xd7\xeav|\x8e" + + "\xdb@q/(\xb6\xed\xf7\xb9\xf3\xfe\x9e\xe6\x17\xe0\x9d" + + "\x83\xe2qP8\xff\xees\\\xab\xc7\x9a\x7f\x04\xaf\x16" + + "\x14\xfbA\xe1\xfe\xc2\xe7\xde\xfb\xe7\xb0\xaf\xf6\x83\xe2\x00" + + "(\xb6?\xe7s`\xabW\x9b\x1f!${\xa0Y\xa3" + + "\x03\xa9\x08m\x1a{\xd6\xe7\xde\xfb\x8f\x9a\xdf$$\x1b" + + "Mi4\x9b\x00E\xe1\xe7>G\xb6jJa\xec\x09" + + "\x14sA1\xfe3\x1f\xdd\xf7\x8b\x8fLE(!\xd9" + + "cA\xb3\x084\x7f\xfb\x8c\xcf\x1d\xf8\xc7\xa7\xe0\xae\x96" + + "\x80\xa2\x0f\x14\x9fz\xda\xe7\x1e\xfc\xb5)x\xf2>P" + + "l\x06\xc5\x8e\x9f\xfa\xdc\x85\xbf1\x05/j3(F" + + "@a\xff\xc4\xe7>|\x86W7A1\x06\x8a\xe1\xa7" + + "|\xe4\x02^\\N-\x87\xab\xef\x02\xcd%\xa0\xe9|" + + "\xd2\xe7l\xc0\x17\xa5\xc0\x90\xd8\x0d\x8a\xbd\xa08\xf7\xc7" + + "~\x9a.\x85\x17\x92\x82>\xd9\x0b\x8a\xeb@\xf1\xe5\x1f" + + "\xf9\x1cAk\x1f*\xae\x03\xc5m\xa0\xd8\xf9\x84\x9f\xa6" + + "\x9f\x83\xaf3\x05\xfd~\x07(\x1e\x00\xc5\xae\xc7}\x8e" + + "\xadu\x1f\x1e\xf1\x00(\x1e\x07\xc5\x05\xff\xe6sp\xad" + + "\xc7R\xd0\xbd\x8f\x83\xe2YP\x9c\xf7\x7f\xfc4]N" + + "H\xea\x99\x14\xf4\xef~P\x1c\x00\xc5W\x1f\xf3\xd3\xf4" + + "\xf3\xf0B\xf0T\x07@\xf1\x0e(\xa2\x8f\xfaiz2" + + "!\xa9\xb7S\x08\xd9\x0e\x8a\xf7@q\xe4\x0f\xfd4]" + + "AH\xea\xdd\x14\x02r\x81\xe2CP\x94\x1e\xf19\x82" + + "\xd7\x07x\xaa\x0fA\xd1\x90\x8e\xd0\xa6\xb9\x0f\xfb\x1c\xc2" + + "\xab.\x0dGD\xd3\xf0rA\xb1\xfb!\x9fCx5" + + "\xa5\xe1\x88\x04(\x8e\x00\xc5W\xfe\xd5O\xd3\x0eX\x88" + + "\xd3\xf0\x0a\xe7\x82b!(\x8e\xfe\x17\x9f\x83{\xcdO" + + "\xc3\x072\x0f\x14K\xd2`\xae\xf6\xa5i\x17\xa5\xa9\xd6" + + "4\xcc\xd4\x0bA\xbe\x0c\x0e\xb8\xf4A?M\xbb\x09I" + + "-M\xc3\xcc\xb0\x0c\x14\x83\xa0\xf8\xf4\x03~\x9a\xf6\x80" + + "!\x8bg\xea\x03\xc5fP,\xf8\xdf~\x9a\xae\x84\xc1" + + "\x90\x86\xd9g3(F@q\xf9\xfd~\x9a\x9eJ\xc8" + + "b\x96\xc6\x11g\x82f\x0c4\x7fw\x9f\x9f\xa6\xab\xe0" + + "{NC\xef\xee\x00\xc5nPh\xf7\xfai\xda\x0b_" + + "g\x1a>\xa9\x0b@q\x19(\xfe\xea\x9f\xfd4\x18\xac" + + "\xa9K\xd30\x14/\x03\xc5\xb5\xa0\xf8\xcc\x0f\xfc4=" + + "\x8d\x90\xd4\xd5i\x8cQ\x83\xe2:P\x1c\x7f\x8f\x9f\xa6" + + "k`\x94`'^\x0b\x8a\x9bAq\xc2\xdd~\x9a\xae" + + "%$uS\x1af\x80\x9bAq7(N\xfc\xbe\x9f" + + "\xa6\xa7\xc3\x1c\x9e\xc6\x80\x15(\x1e\x00\xc57\xee\xf2\xd3" + + "t\x1d\x0c\x9f4\xc6\xa9A\xf18(\xa6\xdf\xe9\xa7i" + + "\x1f\x0c\x9f4V\xc9\x83\xe2iP4\xdd\xe1\xa7i?" + + "\xcc\xe1i,\x93\x07\xc5\xeb\xa0\xd8\xfb=?\x0d\x06v" + + "\xea5|Qo\x81\xe2 (\xae\xf8\xae\x9f\xa6Y\x98" + + "\x91\xd3\xf0I\x1d\x04E\xb4%B\x9b\xae\xbc\xddO\xd3" + + "ABR\xb4\x05^H\xb4\x05\x06\x03(N\xbe\xcdO" + + "\xd3\xf50\x18Z\xe0\xe2\xd3@1\x0b\x14]\xff\xe4\xa7" + + "\xe9\x06BR--\xb0\xac\xcd\x02\xc5\xb1\xa0\xe8\xbe\xd5" + + "O\xd33`y\xc6#\xe6\x82b!(zn\xf1\xd3" + + "\xf4L\x18%-p\xf1\x85\xa0X\x06\x8a\x957\xfbi" + + "\xba\x11FC\x0b\x0c\xb8e\xa0\xe8\x06\xc5_\xff\xa3\x9f" + + "\x86\x8dN\xaa\x03\xaf\xd1\x0d\x8a>P|\xf3;~\x9a" + + "~\x11\xe6\x8c\x16\xf8\x06\x07Aq6(\xe6\xdd\xe4\xa7" + + "\xe9fBRg\xb5\x805\xb1\x19\x14#\xa0h\xbf\xd1" + + "O\xd3\xb3`\xceh\xc1\x14fP\x94@q\xd4?\xf8" + + "i\xfa7\xb0n\xe35J\xa0\xd8\x01\x8a)7\xf8i" + + "\xfa%\x98\xf5\xf1\x881P\\\x00\x8a\xa9\xd7\xfbiz" + + "6\xcc\xfa-\xd0\xed\xbb@q\x09(\xa6]\xe7\xa7\xa9" + + "\x0e\x93L\x0b\xbc\xf3K@q\x15(\x1a\xbf\xed\xa7a" + + "\x83\x94\xba\x02\xefj/(\xae\x03E\xc3\xff\xf2\xd34" + + "\x07\xc3\xa7\x05\x91\x03Aq3(\xfe~\x9f\x9f\xa6y" + + "\x18>xW7\x83\xe2nP|\xfdZ?M\x19\x0c" + + "\x9f\x16x\xb5\xf7\x82\xe2QP|\xe1[~\x9a\x0e\xc3" + + "V\xa9\x059'@\xf18(\x16_\xe3\xa7i\x01\x86" + + "\x0f^\xfcQP<\x0d\x8a\x8b\xae\xf6\xd3t\x04\x86\x0f" + + "\xbe\x8f\xa7A\xf1\"(\xae\xba\xcaOS\x83\x90\xd4\xf3" + + "x\x8dW@\xf1\x16(.\xfe\xa6\x9f\x86\x8dX\xea\x8d" + + "\x16\xf8\x08\xdf\x02\xc5AP\x9c~\xa5\x9f\xa6[a\\" + + "\xb5\xc0\x87s\x10\x14\xd1\x19\x11\xda\xb4\xee\x0a?MM" + + "\x18W3\xce'd`\x86F\xb3\xd3@\xde\xb7\xd7O" + + "\xd3\"!\xa9\xc6\x19\xd0U\xd3@1\x0b\x14\xfd\xdf\xf0" + + "\xd3\xd4\x82a\x05\x07d\xd3\xa0\x98\x0b\x8a\x81=~\x9a" + + "\xda`\x1a\xa0\xe2\x08P\xcc\x03E\xf6r?MK`" + + "\xf5\xa1\xe2XP,\x02\xc5\xe0e~\x9an\x83\x15\x07" + + "\x15\x0bA\xb1\x0c\x14\xeb\xbf\xee\xa7\xa9\x03\xe3\x0d\x15K" + + "@q\x0a(6\xfc\xbd\x9f\xa6.!\xa9\x15\xa88\x19" + + "\x14\xab@q\xc6\xa5~\x9az\x84\xa4zP\xd1\x0d\x8a" + + ">P,\xba\xc4O\xd32\x0c\xc4\x19\xb0\x9e\x0f\x82\xe2" + + "lP\xb4\xfe\x9d\x9f\xa6\xa30\x10g\xc0\x1a\x95\x07E" + + "\x09\x14m\x17\xfbi\xba\x1d\xc6\xdb\x0cd\xd9\x04\xc5." + + "P\xac\xba\xc8O\xd31BR\xe7\xce\xf8\x13\xccJ\xa0" + + "\xb8\x0c\x14\xbd\xbb\xfd4\x1d\x87Yi\x06\xccc{A" + + "q\x1d(V\x7f\xcdO\xc3~9\xb5o\xc6\xcf\xc0f" + + "\x00\xc5\x1d\xa0\xb8\xec\xab~\x9a\xfe-\xd8\x0cx\xc4\xdd" + + "\xa0x\x08\x14\xa7]\xe8\xa7\xe9\x0e0\xf4g\xc0g\xfe" + + "\x10(\x9e\x04\xc5\x9a\x0b\xfc4=\x17\x0c}T<\x09" + + "\x8a\xfd\xa0X\xfb\x15?M\xbf\x0c6\x03*\xf6\x83\xe2" + + "\x00(Z\xce\xf7\xd3t',Q3\x10\xd8\x06\x14o" + + "\x81\xe2\xb3\xe7\xf9i\xba\x0b\x06\xc9\x0c\x1c$\xa08\x08" + + "\x8a\xe3v\xf9iz\x1e\x0c\x92\x190\xed\xbe7C\xa3" + + "\x033#\xb4)\xb6\xd3O\xc3\x8e/\xf5\xd1\x0c\x98C" + + "?\x84\x03\x1a@\x91\xf8\xb2\x9f\xa6_\x81\x15j&\x98" + + "\xa2\xd1\x990)\x81b\xe6\xb9~\x9a^\x00\x93\xd2L" + + "\xb8D\x02\x14G\x80\xe2\xd4\x1d~\x9a^\x08+\x14\x1e" + + "1\x0b\x14\xc7\x82\xe2\x98\xbf\xf5\xd3\xf4\xab0)\xcd\x84" + + "\x8fy.(N\x06\xc5\x8as\xfc4\xfd\x1a\x18\x963" + + "\x11\x88\x0d\x14}\xa08s\xdcO\xd3\xdd\xf0f\xf1\x1a" + + "}\xa0\xd8\x0c\x8a\x8dc~\x9a^\x04+\x11*6\x83" + + "b\x04\x14\x9b\xb6\xfbiz1L1\xa8\x18\x01\x85\x07" + + "\x8a/\x8e\xfai\xfaw\x84\xa4\xb6\xa1\xc2\x03\xc5.P" + + "l.\xfbiz\x09\xbcrT\xec\x02\xc5%\xa08\xcb" + + "\xf3\xd3\xf4R\x98IPq\x09(\xae\x02\xc5\xdf\xb8~" + + "\x9a\xfe=\xcc$\xa8\xb8\x0a\x147\x82\xe2K\x8e\x9f\xa6" + + "_\x07\xfbq&\x8c\xd0\xeb@q\x1b(\xce\xde\xe6\xa7" + + "\xe9e`\xae\xcc\x04\x1b\xf5FP\xdc\x01\x0a\xbd\xe4\xa7" + + "\xe9\xe50Hfb\x89\x0c(\xee\x06E\xc6\xf6\xd3t" + + "\x0fL13\xe1\xcd\xde\x01\x8a\x07@\xb1\xc4\xf2\xd3\xf4" + + "\x1b\xb0Ba'\xde\x0b\x8aGAqJ\xd1O\xd3\xbd" + + "0\xf7\xcc\x847\xf8\x10(\x9e\x04E\xce\xf4\xd3\xf4\x0a" + + "\x18V3aM{\x12\x14\xfbA\xd1\xb1\xd5O\xd3+" + + "aX\xcd\x84\x09c?(\x0e\x80\xe2\xd8-~\x9a~" + + "\x13\x86\xd5L\xb4|@\xf1\x0e(\x96\x1b~\x9a^\x05" + + "\x96\xcfL\x98\xc6\xde\x02\xc5\xc1\x99\x11\xea\x9bv\xa1\x06" + + "\x9a\xa6!\xa0\x10xi\xc4\xe6\x1f\xb4\xff\xeeG\x0d\x89" + + "\xdf\x06\xbbuKw\x1c{\xfb\x80M\xf5|\x17\x96\xc9" + + "s\x9eg\x9a\xf0\x17O\xf9\xee\x15\x7f\xe8\x89\xbc\x19\xb4" + + ",\x94\xdc\xd3\xd7\xf6ttSInG\x13\xfe\xee\xd5" + + "\xf7\xa7\xc6\x8e\x9c\xbf/\xa4(\xc52\xc6\x9eQ\xca\xb0" + + "\x08\x7f\xa0'\x83\xa9\xf94\xe1_?\xbf\xe7Y\xe3\x9a" + + "\xbbn\x08\xf2\xefsz\x98+\x99xy\xe3\x8e5W" + + "^s\xe1\xd7\x84\xa76/|\x90\xdc\x11\x91\xf0\x7f\xb7" + + "\xe7\xc6\x05\xdf\xbbg\xff\x8d!n\x81\x80\x85&\xe1\xcd" + + "\xbe\xfbO\xf4\xc4\xc7\x0c\xff\x9ba\x89\x841\xcazF" + + "\x99E=Q\x1e\x10\x83\x9b\x08]\xc3G\xb5m\x9ev" + + "\xcb\xfd\xff\xbcW\xb8\x863X\x15A\x13\xfe-\xf3~" + + "\xef/\xfc\xc5\xad\xf7\x86\x85\x0a\x0c!\x19]\xaa\x00\x0c" + + "\xd0\x84\x7f\xceW\xdf\x1c\xbc\xeb\xf6\x97\xbf^\xeb\xa1]" + + "h*\xf8\x1c\xe5\x05\xd5\x87\x9f\x1eP\xf6r\x88S%" + + "z\x05w\xb6\xf1@\xf9\xb8\xff\x95\xff\xc7\xe0\xd4\x01\x16" + + "*\xd2\xf1'\xfc/=\xfd\xd1/.\xca\xce\xbaF}" + + "\xce\xf5\xbd\xdd=\xb4\xa2\x06\xe2\xed\x0f\xbf{\xe5\x07\xa7" + + "\x9c\xffP\x8d\x97\xcc\xdd\xdd\xb1\xdeZ~f<\xdb\xa0" + + "\xa3\xe7\xe8VW\xbd\xab\xf0)6ullM\x9cm" + + "\xdf)\x9eb\xa7\xcb\xac\xfc!^#\x8cG\xe6\xba:" + + "B\xa0\x07E\xe4\xa6\x88!S\x11v\x80\xfb}\xe0\xb2" + + "\xaf\xac-\x97^\xbe2\xac\xd7)1PZ\xb4\x80t" + + "b\xc55\x9a]\xa0\x09\xff\xc1}\xdf\xbfwe\xd3\xd4" + + "\xd7\x95\x11\x89\x90$AQ\xd0\xf4\xe7n\xdf\xb8j`" + + "\xe5\x1b\x92L7\xa8\x9a\x85\x8b\x9c|\xd9\xc0+\x8d\x7f" + + "\xbaq\x9f\xa2Exq\xa2\xd9\xf0\xea\xbf\x97\xbe\xf7\x9a" + + "\xe8\xfc\xdd\x7f\x0c\xfbBd\xe1\xd3\x80}\x86Cv|" + + "\xad\xf9\xfe/|q\xea+j\x8f\xc1=\xd0\xa0\x12%" + + "x\xf3\x09\x7f\xdey_\xbe\xe9\xdf\xfe\xea[\xf7\x05M" + + "\x03\xa0\x18\x0a\x1fc\xcdA\xb2\xf1\xcc\x9f.\xfe\xe2\xbe" + + "kn\x09\x06\x89\xa5\x8f\xae/\xe5\xb1\xaa@\x19\xc4\x09" + + "\xff\xc7[\xfa\x19\xfb\x97\xab~)a" + + "\xd4Q\x1a\x9e\xf5'\xdb\x1f9ox\xc3\x1f\x7f\x1a\x9c" + + "u\xbb1ld\xe1\xad\xd5l=\xf5\xfe\xf3?={" + + "\xd3\xcb\xcf\x86\xb5<\xdc+|*\xb5\\\xb7\xf2{~" + + "\xf0\xc2G\xdb\x9f^\xf4\xf2\xcb\xc1]l\x13\xf9\xb1\xbc" + + "\xb7\x1f\xee\xffn\xec\xb4\xc2\xde\xff\x90\x1d\x95\xd7\x9d>" + + "o\xc2\x97\xf4\xf5}\xa7\x9f5\xf2\x8b_\x07\xbe\xe5\x12" + + "g,\xa4\x09\xbf>=\xd2\xfe\xb7\xcb.\xfc^p\x82" + + "\xb2\xa8\x18&\xd4\xa5\x09\xff\xac?\xfd\xe47;^z" + + "\xe9\xc2\xa0\xca\x07\xb3\x18@1k\xe5\x8b\x7f{\xcd\xdd" + + "_zB}AkK\xb9\xaaY\xeb\xba\xb6/\xdd\xdc" + + "\xf6\xeb\x9b\xf6T\xbeF\xab\x10\x09\xe8\x86\xe0\x90\x8a\xa7" + + "\xfd\xd5\xa6\xaf\xae\xeb\xda\xf1\xaa2o\x8eb\xe6\x03u" + + "+\xdf\xcd\xb4\xe6y\x8d\xcd\xc7\xec~\xb0\xe2\xb6\x07\xf4" + + "\xed\xd0+A\xc8&@\xcb\x8d0\xa7\xcf6\xc4\x94!" + + "\xfb\xe4\xbf>8x\xf5\x95\x8f\x0d\xfe\x932\xcc\xc3\xe6" + + "a\xb4;\xfc\xd6\xb7\xbe\xf4\xf0S\x97\x1dy\xfb\xfba" + + "ez\xa9d\xea\x961F\x07\xf4\xed\xea#\x04\x17\xf7" + + "\x1c}x\xd8\xc8\xf5DF\x99r\xe5\x8a2\xb4\xcf|" + + "\xe67{\xaf\xf3\xfet[X\xb1&\x06y\x84W\x8c" + + "\x15\x0d\xabP9iU\x0fu\xdb\x19rM\xbd\xd8\x15" + + "\xe1\xe4\x9c\xb2HKt\xd2\xad\xaf.\xfd\xd6\x8b\x8b?" + + "\xba\xb8\xfa+\xd2\xa0iH\xb1\xaa\xde[\xcdk\xac\x1b" + + "r\x99\x13\x19\xd5'T\x81\x85O\xf2o\x1fo\xe9:" + + "\xbd\xd8\x16\xe2\xe6\x043\x065l\xabg\xcccN\xcc" + + "\xd2\xcd\x1a3\x87)\x90\x8e\xaaFk\xf5=\x94\x8d\xd3" + + "\xf5Q\xa3\xc0;\x06k\xb1*\x9f\xf3\xf3/\xdd\xfe\x05" + + "\xb3\xf3\xf1\xcbj>'GQ\xea\x0e\xebS\x0e={" + + "x\xcc\xf5V\xdb\xe3.\x89{Fn+\x0c\xc8\x96\xcf" + + "\xfe=\xa3\xc7\x1eP\xfb#o\x17\x19\xf5\x9c\xf1\xca\xa1" + + ";\xfa\xc5\xcc\xdb\x1b\x1bJ\xff\xae\xb4\\\x09\xeb\x1au" + + "X\xd5'\xfd\xfb\x8d\xf4\xe2\xd53\xce~\xaaz,E" + + "\x02\xe4\xa7Cw\x87\xed\x0c\x9d\xc6\xc6W:T/\xb2" + + "\xca\x13\x1f\xfb\xe5_\xf5h'\x7f\xfaq\xd9qk\xf4" + + "q\xbb\xecE\x14\xda\x96\xe0E_\xf7\xd2\xfc\xdb\x1b~" + + "\xf2\xe2\xee\xea\xdb\x8d8\xcc\xcd\x96\x8bE]<_0" + + "\xfa\xfeu\xdd\x9f\xb43\xa7\xfd\xfc9\xd1\x9e\xf2\xf67\x1e3O\xbeW\xc4" + + "T\x87l\xdb\xa3\x09\xbf\xf7\xb8s\xf6\x94\xbez\xc2\xf5" + + "\xea+\xea\xd3\x1d\x9d\xb4\x17\x99\xc7\x1c\x98R\xb2\x9f\xdd" + + "q\xe5\x8f/\xad{\xbebJ\xd1K\xddT\xcc\xe3\xf2" + + "1\xbf\x93\xfc\xe37\xbe\xfe\x99/\xec\x95K\x0cXT" + + "\xeb\xf2\xa4\xdd.2\xcf\x19\xa7\x09\xff\xca9\xcf~{" + + "\xeb\xfck\xfe$k9yQ#\x0d\xbe\xec\xf0dG" + + "\xdd\xf3\xfa\x82\xbfo}\xe3\xd5JF\xdau\xf9\x08?" + + "W\xd54\xb0||\xd9\x9b\xff\xfc\xa9_\x853\x9aJ" + + "\xdf\x93\xf0\x7f\xfe\xc7)\xcd\xf9\x9f|\xe9\x07\x01\xe1r" + + "\x08\xa1U\xc7k\xcbD\x95\xe1\xe4\xf6\xcb\xcf\x97\x7fo" + + "\xcd\x7f\x9d1C\x02P\xe9\x0e\xf4R\x91\xcf\xc6/\xdc" + + "r\xebe\xc7~\xce\xb8D>\xf7\x90au\xe9E\xca" + + "\x1c]\xe2VT\x1b\x94\x01\xce\xb7V\x83\xc3'\x18\x0c" + + "\x17\xdcp\xe4\xea\xc6\x17N\xbe\xb7\xfa\x0b\x8a(_P" + + "\xc5T4\xff\xe1\xdf\x1e\xb5\xa2\xf4\xd8\xef\x14\xd3\xcc3" + + ",f\xf2Ui\x99\xf5~\xf7\xcf\xce\xd7~\x1fh\xb7" + + "\x1by6`\xeby\xcam_\x9e\x021\xf1Vwr" + + "\xa0\xbf6\x9a\xf0\xdf\xf8\xa7\x13\x9b\xb6\xb6o{\xb4\xe2" + + "Q{\xac\x1ci\xb7\xf3\xac\xb6U\x15^D\x00k\xe5" + + "i\xadVE\x91\x07!\"\x97\x09\xff\x8b9c\xce\xf7" + + "\x07\xb7\xfd4\xfcfJ\xa6\xad\xe7\x99S\xeb\x9b9j" + + "\xe5\xd6\x7f>i\xebg\xc2\xd5\xb6$\x12\\\xa8(\x83" + + "\x836\xbb\xcf\xb9p\xc97\xdf\xbb\xf7'a\x1ba\x82" + + "\x92\x98\xa7B\xf0\xa8\x06\xa80B\x100*R\xce\xd5" + + "\xa8\xb6\xfd^\xe4\xab;\xef\x9aq\xfe\xc3\xca\xb2\x88%" + + "\xb3U\x13\xe7\xcf\xbf\xd9\xd4\xfd\x87\x81\xf4w\x94f\x98" + + "\xe2C-\xdd0+'\xbe\xaa\xa1\xea#\xeb<\x98\x04" + + "hJ\x16\x98\x84#\x9a`\xd5\xc6\x11K!\xe1\xbfs" + + "\xe1K\xeb\xbf\xff\xe65?\xad~G4H\xf4\xa8\xd1" + + "\xa6\xea%u\xebZ\xcdSm;\x9d_\x94\xda\xe2\xa2" + + "\x196\xc9E'\xb4\x8cO2<\x0a\x02\x94%\x12\xa0" + + "\xb2Tv]\xe3\xbe\xe9g\xcc(=\xfb=R5\xbf" + + "\x91\x0c\x96\x01\xd2\x84\x7fG\xae\x9c>e\x1a\xfd0\x1c" + + "(.s:m{+\x89\x17u\x07\x96\x8a\xbeo]" + + "z`\xdf\x96%\x1fW\x98\xf9\xb6\xb3\x8d\x96q\xaa+" + + "\xb2\xb8\x98\xe9\xf6\xcch\x9c\xfa\xbb\xcbf\xfcF\x8e\xc9" + + "\x82\xc5<\xbbH\xe20\x17N\xdc\xc3\xf9\xa6Q\x18\xf1" + + "\xb2\xcc\"1\xd7\xae\xa5\xf7X\x11MyZvX\x16" + + "6I\xb4V+Q/n\x93Lq\x92\xeb\x14\xc6\x1d" + + "\xdb\xcd\xd9\x98\xb90\xb9\x96\xb2\xb6\xca\xc9`\xb2\x0bE" + + "\xf0:mUc\xb9\xaa\xf5\xce\xb2\xd1\xcd\x86\xca`\x8b" + + "\xfe\xf4\xcd?\xd9\x17\xdd\xbe4\xec@\xd7.[\xf9>" + + "\x87\x91\x8c\xeb\x96\x1d\xb8\xa5O\x9f\xed\\vQ\xea\xd8" + + "\x17\x95\x01\xce\xe9\x01\xaa\xcc\xdd\xba\x7f\xf9\xdc\xa3\xaf\xad" + + "\xb8Mvpi\x80Yy\x16q\xaa?j\xb8\xa1O" + + "\xdd\xfc\xa75\x0b^:\xf3z\xb9jr\xfb\xafr\xb3" + + "\xf7\xf0gO\xfa\x9b;\xbe5-|\xfd\xae\xa7;%" + + "\xc3\xb4\xa9\xc7\x8d\x13O\xec\x8e\xbe\xf7\xde\x9a\x936\xbd" + + "\xf3\xc8y\xe1WQv=\xbb8\xc0\xa8\xcb\x9cQ\x96" + + "o\x85s\x9du\xcfo[\xbf\xfe\xd1\xcb\xdf\x9dx\xae" + + ".]\xa4h\xd1\x84\xff\x88\xf5\xafS7<\xba\xf9\xbf" + + "&9\xd3b8\xd3\xd25\xdd_\xb9\xea\x8c+_\x98" + + "\xa4\xcd\x12h\x93\xdc\xba\xf1W\x96\xf7\xdd]\x93\xb4Y" + + "\x0am\xd6\xdf\xd8\xff\xfc\xc2\xd1\xa7n\x9a\xa4\xcd\x89\xd0" + + "\xe6\x1f\xa2\xa5\x8f>\x7f\xc1\xa5\x1fL\xd2\xe6s\xd0\xe6" + + "q\xba\xe6h#g\xdd;I\x9be\xd0f\xf6\xbe}" + + "\xbd\x8do\xcdxo\x926'A\x9b\xe3\x7f\x99\xd1\xba" + + "c#\x15\xf6\x82\xeb9,\xa2\x17\xc5\x07/\xbe\xf7\xcc" + + "d\xcb\x81r\xc4\x19b\xd29\xec\xa6\\\xb4\xef\x12\x13" + + "\x19_j\xf0\xed\x1f\xa2u\xe5\xfd\xb4\xe7'\x9b\xa9&" + + "\xbd\xa1\xf8\xe1\x0fP\xee\x08\xb3gj\xb4\x0e\xe6\x80H" + + "0\x078\x87\xf9J\xab\xba}@o\xdf\x0e7\xb2(" + + "\xdc\xc2L\xd2\xa0\xf5p\x0d\xdad\x03\xddYW\xf6J" + + "eB\xc1\x06\xbc\xf0G-\xfd\xec\x173\xf7\xabS\xac" + + "a\x15\xd6\xd2 ?\x08{z\xf4\x1f\xbfq\xf5y\xf7" + + "\x7f\xf0z\x85\xa5h\xbb\xc2\xbb\xb0\xf6\xeez\xe7\x9e\x1b" + + "\xd6<\"\xed\x0eN\x8bJ\xdaY\xe0\xa3\xfa\xfc\xcd\xef" + + "\xadzq\xd1\xb1\xf7T{[\x88\x86;\xd7\x1f\xdf\xfa" + + "\xce\x11g\xfe\xe2\xe2\xdd\x95\x13}\x87K]\x09\xde\x97" + + "\xf0\x1f\xf8\xe9\xc3\xb7\xb8\xdf\x1e\xfeV8\xa5\x99\xcc\xf1" + + "\xba\xd9\x10\xd1p\xa6\xda\xf0\xd5\xc2\x91\xf7\xff\xe1\xc2p" + + "7\x18Xv$~H\xa6\xb7\x8cg\x97s#R\xfd" + + "\x837\xff\xd4=\xff\xa9+\xbe\x16\x9a{Us\xc5\"" + + "nsn<\xa3d>\xf7\xed\x1fO6\xa3\xb4b\xab" + + "\x0b\xb4%\xaf\xb0\x93\x8f}d\xb2Vm\xd8\xaa\xf9n" + + "Z(<\xfe\xd4\xb5\x93\xb5Z\x8c\xad\x9e>\xff\xba\xc2" + + "\x9f_\xb8\xf2\xa9\xc9Z-\xc1V\xed/\xbfy\xee\xda" + + "\xb9g\xdc1Y\xab\xa5\xd8j\xe4\x81o\xec\xcd~\xbe" + + "\xfb\xc1\xc9Z\x9d\x88\xad\x92?\xd8\xbe\xfb\xed\x8e\xa1\x0f" + + "\x95\x19;\x0f;Gj\xe5Y~]\xd9C\xa7\x90\xb6" + + "\xf8\x94\x83C\xf5\xff\x108#\xa0M/L\xb9\xbf\xff" + + "\xfe\x17\x9eY\xb6b\xcb\xe3\xa1\x19\xa9\x97\xe0\x18\x9a\xf0" + + "\xcf\x7f\xff\xfdO/\xfe\xdd\xbb7\xaac! \x80N" + + "\xf8\xcf\x1e\\\xfb\xe81\xbf|\xf9*\xe9\x04\xdc\xdeQ" + + "\xce\x1b6\x09\xbe\xc8\xd7n\xbf\xf7s\xbf\xdc\xf6\x9b\xf0" + + "\xf0!\xdb\xde\x0a\x8b=i\xef,{\x1eN\xf7\xd5\x8b" + + "\xbe\x0e'X\xc9X$?\xa4\xe7\xb6V\x9a\x8f\x0b>" + + "\xf7/\xe5\x87~}\xea\xdbU\x9b\x92\xb5T\x80A\xf6" + + "\xc5L\x1d\xce\xb9\xe8\x84\xd2\xdeG\xdem~\xbb\xda\x82" + + "\x0f\x99zB\x7f\xec\xf1u\xef\x9e{n\xdf\xcb\xd7\x85" + + "\x9d;\xc2\\\xcf*{\xd2c{\xeb\x0f\xf7\xddyD" + + "\xfc\xdf\xbf^\x8dE\x1b\xfb\x04Y\xcb\x1b\x0c\xd7\xb0\xad" + + ">\xdb4r\xe3\x02\xa4\xd5vy\xdd\x85\x92\xbf\xdbV" + + "+\x7f\xf7\x18\x99\xbf\x1b\x80\x10_\xbf\x89\x90\xfe\xeb4" + + "\xda\x7f\x9b\x92\xc5}\xcbj5\x7f\xf7\x14\x91\xbf\xbbI" + + "\xa6\xea\x86\xf9\xbb\xf7\x0dIP\xbaL\xc9\xf0r!\xd0" + + "yl\\\xf21\xf9\xa8\xe9B\xac\xf0!0\xda\xde\xe8" + + "\x9f\xf6\xc8\x96\xb3\xc2Yr\\\xdf\x8e\xb9\xd8|6\xa9" + + "\xd6\xaa\xa52\x12\xa0$`g\xac(\xf3:,\xb7O" + + "\x90\xf2\xa7\xb1|\xff<-J)f\xc85b\x1a-" + + "f \x1e+\xf0WA|4f\xb3J(\x19-\xca" + + "\xd3\xe3\xe6c\xd6\xaa\x84\x8c\x89\x89J\xf4V\xccr\x0d" + + "\xc1\x1a\x13\x02\xeb\xe1$<\xbb\xe4\xf0\x89j<\xa1\xad" + + "\x03\x9b\xcb\xa4\xde:\x81\xf5\xd0\x8b\xc9\xb5!o\x10\x16" + + "\xb4O!$\xb5\x16\x93_\xd7\x84\xc9\xbb\x0d\xd1 y" + + "\xf7\xe2\x8ad\xdc\xc6(OfS\x92q/\xa1\x87\xc1" + + "'\x09Q\xdec\x15I\xeb5PKj1\x99\x0d{" + + "\x13i\xc9\xe0\xe0\xae\xf1\x9c\x89KD\x90-\x9b\xd3M" + + "\x84\xc3\x0aOv(J\xb2\xd0\x85M\xf9\xd9\x8b\xb0\x08" + + "T\xd0\xa4\xf58\x0e\x89)X\xd1q\x7f\xc5#\xeb\xfe" + + "\xe3\x87\xa3\xce\xcb\xd5i\xefUP\x90\xc2\x13\x16\x96q" + + "\xe1\xca\x8c5!\xfcC\x9a\x87\xdf\xc66^kap" + + "\x8as\x9dS\x9co\xe4\xb8\xc6\xeb9d\xfa\xda\xd5\x88" + + "k\xdc\xdb\x86\xb8\xc6\x1dp@\x03\xc2\x1b\xd3\xc6\xe4\xd2" + + "NBv\x0a\x17r\xccX\x97\x8d\xe5t\x07\xb1\xba\xf2" + + "\xe3\x16\xf4J\xfbp\x19\xbed\x9f\x8dy\xcc\xb10\x19" + + "8\x83\x1e\xd3\x9d\x9ec\x14\x87L\x86^\xe5\xbc\xa1\x17" + + "\x08Vy\x189\xdba\x93$\xf2\x9bva\x03s\xe0" + + "t\xa4\x8fR\xe8\xefd\xf4\xd0\xf08|\xf3\x03{\x1f" + + "\xec\x82\x00\x1f\xb5F\x19D\x9b\xc8v?E\x99JV" + + "\xc0T\xb2\x8c\xb3\x0e}R\xec\xf2\xc9X3T\xa2{" + + "\xce\xdd\x157\x0do\\\xa9y\xd9\x84\xefa6\x87\x92" + + "m\xe9$\xc4\xd7\x0b\x05\x87\xb9\xaeA\xb4Q\x06\x86\xba" + + "\x95\xd7\x9d" + + "\xad\xdc\x82\xedo\xac\xa0;oD\xbash\x7f\xafD" + + "in\x08P\x9a\xa1\xfd\x93\x01\\L\xbc\xa4fQ\xc3" + + "\x0f\xfe\xe5\x85_\xfb\x04 \xca\x09`\x96\xb5\x90)'" + + "\x00\\\xd6\x82\xaa\xa4\xa3\xd5\x8dFk4\xd2\xab\x1b\xe9" + + "\x87\x00\xb8\xac\xab\x0dc\xa2\x00\xc1\x8aR0\x85)\x81" + + "WQ\xf6tV0%\xf0\xcf\xbeu5~\xf6\xc7\xf3" + + "\xcf~\xfe\x02Bb\x85\x92\xbbS\x94\xa2\xb7\x0f1#" + + "o\x97}Q\x91\xb5\x98`m \xfe\xbfD\xf9\x7f)" + + "!$\xee\x0e\xe9\xeea\xcbAz\x8bz\x01\xf7\x0d\x9a" + + "\xed(e\x9e|^:z9\xde\xe0l^d\x9a\xec" + + "\x94\xa5`\xed\xba\xb3\xa8mq\xebN{l\xd1\xe2\\" + + "\xeb\xa2\x9d\xb6\xbbhI\xaeu\xd1a\xe1h%1\x17" + + "v\xc7m\xe1'qS\x14\xc6\xc8uQ\x18kQ\xe5" + + "\x93\xb8\x05\xe57\x82\xfc\x8e\xa8\x82\xaat{\xb4\x8d\x90" + + "\xec\xcd \xbf;\xaa\xa0*\xdd\x19=\x86\x90\xecm " + + "\xbf7\xaa\xa0\xa9\xde\x83\xe7\xb9\x03\xe4\x0fD\x158\xd5" + + "\xfb\xa2\xcb\x09\xc9\xde\x0d\xf2\x87\xa2\x0a\xb6\xcb\x83(\xbf" + + "\x17\xe4\x8fF\xc5\x0a\x0c\xdf\xc4\xc3x\xfe\x07@\xfex" + + "T\xd4\x9f \xb6\x0b\xca\x1f\x02\xf9\x93Q\xb1D\"r" + + "9\xca\x1f\x05\xf9\xd3Q\x05\xb9\xfc)\xbc\x9f\xc7A\xfe" + + ",\xc8\xa7\x0aB\x9bg\xb0\xfd\x93 \xdf\x0f\xf2i1" + + "\xbe\xd4>\x87\xf7\xf34\xc8_\x04yS\x03O\x1b\x7f" + + ">\x8a\xecP \x7f\x05\xe4\xd3\x05\xbb\xf8Kx\x9e\xfd" + + " ?\x10U\x98\xb9^E\xf9\x8b \x7f=*\xe8\xc2" + + "\x13\x84\xa4^C\xf9+ \x7f\x0b\xe4\xc9i\xb3\x99\xe7\x8a\xd3:h\xfe" + + "!\xc8\x1b@>+\xc5S\xc5\xeb\xea\xda\x08\x19\xa8\xd3" + + "hv\x1a\x929\xa7y\xa2x#\x9207\x80<\x0d" + + "\xf29-\xb2Q\x90'@~\xd4\x1c\x9e\x1b\xde\x847\"" + + "/\x98\xf9\x14O\x0do\xc1\xe7\x09/\x98\x9c{\x04\xcf" + + "\x0c\x9f\x8d7\x98\x06\xf9\\\x90\x1f}$O\x0c?\xb2" + + "\x0e,\xb1\xb9 _\x08\xf2c\x8e\xe2y\xe1\xf3\x11*" + + "h\x1e\xc8\x97\x80\xfc\xd3\x19\x9e\x16\xde\x8a\xe7_\x08\xf2" + + "eu\x11z\xf4\xb1\x0d<+|)B\x1a-\x01\xf9" + + ")\xf0\xa0\xc7\xf1\x9c\xf0\x15\x88\xb0t2\x88\xcf\x84\xd3" + + "|\x86\xf2\x94\xf0\xf5x\xfb\x83 /\x81\xfc\xb3\x1d<" + + "#\xbc\x88r\x13\xe4c \x9fw\x1eO\x08/c?" + + "\x96@\xbe\x03\xe4\xf3/\xe0\xf9\xe0\xe3(\xf7@\xbe\xab" + + "\xeeP\xdcd\x99\xa2my#\xc1\xafX^b\x82\xfc" + + "\x05\x0ce1}xQ\x00\x1b\x1d\xd3\x87[\x95\xff\xdb" + + "B\xbe1\xc3\xce\xb3P\x91s\xdc\x90\xf6\x0b\xa9\xc0$" + + "\xedWQ\x9e*W\xce\x85\xff\xb3\\N\x91\x87GS" + + "=\x94z\xb6r~#l\xddn\x17YAWNj" + + "\x84\x07k\x86\"v\xc2#2xD\x88\x83\x8d\xbf\xba" + + "m\x0f\x16\xce\xf0a\xbam/\x04\xce\xce\xd9y\xe6\xae" + + "iS\xb8\xcd\x14\x0243\x94g\xdc\xd1\x0e\xf9\x10\x15" + + "p\xdc\xe1#\x14\xf2j\x7f\xc9\xc6\x9e\xa3[n\xd1p" + + "\xa9\xcbC\xd7L\x1e\xe4\x0f\x1b\x1e\xd6\x87\x93\xd8\xa8n" + + "*\xbd\x91\xab@\xf2\xae\x8d\xbe\xfd\xdf\xc3\xf8\xf6\xec\xed" + + "\x08\xcd\xa0\xc0\xe4\xee\xf4l\xa6B\xa5\xec\xf4\xec\\\x05" + + "t\xca$\x16\xe3\x04\xf3\x95\xa3\x83\xfen\xdd?\xfdq" + + "\xfd\xf1?x\x8e$\xe9P\x15\xe0\x7f_\xb8\x94\x1d\x8d" + + "\x1c`GD4\x9a\x9d\x17Q\x96\xb2\xe3\x10\x92\xf9X" + + "\x90/\x8a(K\xd9\xf1\xc8a\xb6\x10\xe4\xcb\"\xcaR" + + "\xb64\x82I\xca \xef\x8e(KY\x07B8#\x97" + + "\xdb\x9a\x88\xb2\x94\xf5\"\xe7\xd9*\x90\x0f\"\x97\x18\xe5" + + "KY?BD\xf7\x05\xdco4E\xa9?o\xf3\x1b" + + "\xcf<\xfa\x7f\xbf\xfd_$\xb51\x02\xd3Z,\xc6\x97" + + "\xb1\x1eD\x9f\xee\x86\xb6}\xc8\x07\x17\xe1\xcb\xd8Z\x94" + + "\xaf\x01\xf9\x99\x08?-L\xbb\xf5\x91k\x08\xc9\x9e\x09" + + "\xf2<\xc2O\x0b\x02\x0e\x1d\xef=\x1f\xf2\xcaM\x9d\xc2" + + "\x97\xb1\"\xb6/\x81|GD@\x97\xc126\x8eh" + + "\xd8c \xbf\x00a\xa9\xa7\xf1e\xec\xbc\x08\x9a\xa6!" + + "\xdf\xdct\xca\x97\xab\x0b\x91'n7\xc8\xf7\"/\x9b" + + "\x96\x86\x8eN]\x8e\xf2\xbd!\xdf\\\"\x9a\xa6\xcd\x94" + + "\xa6\xf6E\x1e\x01\xf3\x02\xe4\xb7!\xaf\\]\x1a\xfa!" + + "u\x0b\xf6\xa5D\xedn\xaeO\xc3\xdbJ\xdd\x19\xb9U" + + "\xe5\x95\xab\"E*\x8c;6\xe2\x09\x91*\xce\xe9Z" + + ",f\x81\x82\xba\xcc\xeb\x18e\x8e\x9e)0U\xefz" + + "\xc6\xf00\xd2X\xaf\xd4s\x9e\xedT\x11\xa1\x0e\xc0\x07" + + "k\xd8\x87a9\xab\x84\x16\xe4\xfc\x07Y\x12/1&" + + "\x99\xcdk\xb3\x9eU\xdc\xdfJ\xdd\xf5\x10\x83\xf1P7" + + "\x9fU\xf4\xd57_qpx\xff\x19\xc3V\x0e\x8a;" + + "\xb6\xa9\xd2\xf6\xd6\"a\x08?4I\x08\x11\xde\x87\xe0" + + "\x8c\x96\xf1\xf5@\x19\x09n\xb2\xc0\xe4|R'Y\xe3" + + "\x0603e\xa2\xaa\xf2\x116\xc4+\xa3\xf7\x87\xaa\xf7" + + "\xaf\x00\x0bu&2bM\xd3\xa2XI=\x85\x90d" + + "\xcf\x16\x95Y\x8c{V\x90\xca\x08\x99\xc5F\"4\xc1" + + "Ij\x92\x0c\x1a\xe65\xda\xbf+B};\x973\xcb" + + "y\x96\xaf\x02\xa5t\x98\x9e\x1f\x17H\x91U\xfb\x12\xcb" + + "\xf6\x06@+\x8e\xf8D\xe0\x8bk\x84\xb3=\xdc\xa4\x87" + + "h\x01\xc3\xe7?\xf9\xa3\x1b\xbeX\x7f\x1e\xcex\x98\x11" + + "4*2\x02U\x88\xdb6\x05P2\xd8\xc0\x97a\x03" + + "_\xe2\x90\x0e\x81/\xf0\xa26\x15\xd1AP\x09_\xba" + + "E2\x80\xfd7Y\xca\xec\xe0\xc6x\xd5l\xe8h\x0f" + + "\xef\xfe\x90\xce\x9a\xac\x08&\x88\xb2\xfcu%f\x95\x0c" + + "\xd3\xf6\xb2\x9e\xaeU\x10\xce\xac\xc6]Q+\x87\xde9" + + "\x9e\xef\x8a\x8esp\xdbv\xf4&B\xfc \xd0\x97\xf0\xc6\x99!\xd3" + + "\xb0\x0a\x01\xea\xb0A\xb4I\xb1x\xb2\"\x18\xea\xbae" + + "\xcd\xe1H<\xb2\xdf\x1d\xc9\xb7\x1c\x10\x0e$\x8dG\x08" + + "\xe97\xf9\xcb\xa0\x1a\xa5\xfeE\xb7\x7f\xf9\xcbG}8" + + "\xfd\xf7$Y\x86\xa9>\x80P\xd0\xef\x12\xc3\xac\x14\x99" + + "\x18r\x0d?a!\x8f\xa0\xf8\x0cD8`\xf9\xee!" + + "R\x1b\xd44hN\x83\xe6\x19l\x7f\x18\xfa\xe6\x1a\xd4" + + "\x82Y\xcfaV\x01\xac\x10\xa5\xfb\xf9\xa6\xf4x\x0eL" + + "r\xdcj\xce\xf7\xb3\x80\xf3\xfd\xb4)0%%\xdbv" + + "\x10\x89\xdd\xe1\xd9\xa9\xf1\x82m\xe73\x05\x87\xe9\xde$" + + "\x9d\xbc^$\x7f\xc87\xae\x90{\\\xa3\xb0\xa2\x04\x83" + + "\xfb\xe1\x1b\x04\xb9\xc7\xd3\x0aP\xc5S0\x90\x9f\xd4h" + + "\xff~\x85\xdc\xe39xG\xcf\x06\\)\xd1*\xae\x94" + + "\xd7\xe5\xfa\x9d|\x0d\xe6\x82\x03\x1a\xed\x7f'B)g" + + "\xf5H\xbe\xbdE\x92\x07)0\xd8\xfdeVfYC" + + ";G\xa2RU)\xbb\xec\x0a\x18*G\xdf\x8eb\x12" + + "\xcf\x1a\xcaA\xa18S\x09@h\xea\xaeW\xe5\x94A" + + "Y\xb6\xc4\x18\xa1\xf9\x0a\xd9J\xc3d\xa4\x02\x90b\x92" + + "\xd2\xf1\xfe\x9c\x9dA\xdf\x08\xf2~\xfc\xdf\x7f\xbc\xfdO" + + "?h\x9e\xf3\xef$\xd9\xba\xc7\x7f\xe3+f\xd35\xe7" + + "\x1f\xf5:I.\xbd\xc6\xff\xfc\xeb?\xfa\xd4tJ_" + + "#\xc9\x93\xf6\xf8{\xbe\xfa\xb7[\xf7\xff\xfb\xae\xf7I" + + "r\xc5\x1e\x7f\xea\xba\xaf\xbf\xb4\xfao\xae\xfc\x11Iv" + + "\x0c\xf9\x9b\xff\xed\xff\xf4\xec\xfdav\x17Iv\xdc\xe0" + + "\x97\xda\x0as\xce\xdb\xf5\xe7;I\xb2\xe7\x1c?p\xbd" + + "\xd0\xc0\xf7B\x99\x9f\xdd\xc0'/*\xc0X\xe0=W" + + "6\xe4\xe9\xa6\x152\x81B\xeb\x07\x90\xb4$f;\x9e" + + "\xdf\xed\xf06\x14\x9d;\x03\xac$\xa4\xd9\xd1>\xdb\x1c" + + "'\xed\x9c\xb6s\x92PI\x13\x15\xb5\xf1\xc9}{d" + + "\\\xa4)\"\x0a\xe3\x93\xb7\x0c\xc9\xc0H\x93&\xaa\xe2" + + "\x93w\xde \xe9z\x9a\xa2\xa2$>\xf9\xe0jI\xcd" + + "\x13\xd6\xc3'\x1f[NH\xffC\x9c\x8c&c\xda\x85" + + "A\x89{]\x9c\xf8l4!\xbb8\x88\x86\xa8OK" + + "\x13\xb2\xd7\xc3\xb0T\x8d\xe7\xa7\x09\xf9B\xc2v\xa2G" + + "pE\x0f\xdf\x90\x88\xe29\xfa\xf65vA\x86\x8ck" + + "\x03\x91I\xcfm\x06\xb3\xc4qM\x9a{y\xec\xc9\xec" + + "?\xb6\xdeE\x92\xf4~\x7fMu\"\xb9@,\xec_" + + "\xa6Ei\x13\xa5\xfe\xd1\x9f\xdd\xb9\x7fSk\xc7\x7f\x92" + + "\xd48\x82XS\xe1\xc9\xa9F$\x89\x08O\x8e\x01\x1b" + + "m\x89H\x92\x10 \xbdE\xc4\xd3\x0eQ\xf0\xd1\x09\x1b" + + "G\xd8\xef\xfb+(\xf4\x1a\x84\x83\xe4<<=:U" + + "w\xa3s6\x00\x83E\xcc\x89\x0b@~Y\xe0\x9c\x9d" + + "KH\xeaRd\x0f\xd8-)\xf4\xa2\xdc\x13p=\xca" + + "\xaf\x0d\xa9\xf2bu\xdc\x13PM\x957-\xc5=\x01" + + "O v\x05:[\xf7\xa3sv\x1a\xdf\xf1?\x871" + + "\xa2gA\xfe\x0a:g\x9b\xf8\x96\xff%|.\x05\xcb" + + "{:\xdf\xf2\xbf\x86\xed%\x96w\x05G\xc5\x88\xee\xae" + + "az\xb8\xfe\xc6\x86s\xdb\xc3\xb5\x18\x93\xf9\xd6\xda\x16" + + "\xc9`D%\x1c|\xe6$/\x8a\xc6\xe5\x0b\x15(M" + + "\xfa\xa0\xee\x14\x94(\x91\xc0\x1f2\xa8U\xe8f\xa6." + + "\x81\xfb\xda1\xe5\xa8\x1aa\xba\x1d\xe9\xea\xaa\xa5\x99-" + + "\xcc\xd9:\x01\x8c\xda\xb5\xcdQ\xe6\xf4\x8cQ&\x18;" + + "\xb0\xb8'\\\xfeF\xec\xb2\x99\xcfzD\xb3K\xd2`" + + "6M{\xfb\xe0\x88C2\xb6\xe7),\x05(\xeft" + + "t\xa2me\x13\xd8\x03\xea\xff\xd2\xb8+\x07dj\xa0" + + "\xd4/\xbf\xc4\x9c\x1f\xbf\xf7\x0f\x1f\x93d\xe3\xf9\xfe)" + + "o}\xe6\xab\x97\x1c\\\xf1s\x92l\\\xe0w\x1b\xae" + + "\xe7\xe89\x8f\xb2\xfc\xe0x\x89\xb9\x04\xb9\x89T|\x95" + + "\x8b\x95\xc5'X\xbb^r\x94\xc5'\xd2\xc0\xe7\x9d\xd7" + + "\xb6(\x8b\x8fX\xba\xde>_a\xae\x8b6\xf2I\xe7" + + "\xfd-\x0a\xa3\x97\x00\xa7O~\xb4\x80\x90\xfe\x83\x1a\xcd" + + "FUhzJ\x7fV\x01\xbb\x12@\xd3')\xa2\x06" + + "\x07\xc1P_\xdf\xae;\x0c-p\x8eq\xe5\xc1\x02/" + + "\xe2w\x81\x8ed\xdc\xac\xc7$\xcc\x91\xe1\xf2\x87'\xf1" + + "\x9c\xa7\x04m\xf3\xd5=B\x13\xb2\xff\x82\xaa#=\xc7" + + "\xba\x99\xc7*\x0f\x8d\xc3\xf6\x88&d\x07\x07\x99\x8b#" + + "\x8c\x99\x9e]\x8e\xe4FV\xea\xa69\xa4\xe7\xb6V#" + + "q\x85\xa1\xe2\x88\xb5nx\xd8\xb1\xf5|\x87\xc9\x1c\xaf" + + "\x8f9qx\x1a\x19\x8b\xf7" + + "\x97q\x8e\xf7@\xbe\x0b?\x93$w\x8e\x9f\x8bs\xb3" + + "\xa4U\xa5Q\xee\x1c\xbf\x08\xe3\xe8r\xee\x879~\x0e" + + "\xce\xfd\x0b*\xe6\xfe\x86z\xee\xa6\xbe\x07\xe7\xe6\xbbA" + + "\xfet\x10\x80;\x82\x90\xd4S\x08j\x15\x06\xda\x92\xf5" + + "\xdf\xe1k\xcek\x18\xd7\x0f\xe7\xf2\xe4\x94\xe9\xdc[\xfd" + + "6\xde\xcf;\x01\x1dj\xa2\x81;\xab?\xc0%\xe1 " + + "\x88\xa3\x11\x81\x8d\x05K\x14\x8dl\"d \xa2\xd1\xec" + + "4\xf4\xdd4\xf0\x15\xaa\x11\xfdK\x0d OG\xaa)" + + "8\x8a\xa5\x1c2\x09Q\xc3\xb6\x94\x8d;\xa2^s@" + + "$\x1a\xf7\x87\xd3\x9d\xf7/Y]\xf8n\x0d\x88\xa2\xff" + + "1\x8cQ\x1eI\x11lL\xe3\xa8\x9e\xfd\xe3%\xd7\x98" + + "HO\x10p\xbcklr];\xd2\xb9O\xd0\x97]" + + "\x04@]C\xe2\x06\xccg\x92\xd5\xe6P\x8b\xccd\x0b" + + "&?\xaa\xcb&\x9a\xab0\xb1\xaa\x03\x97&\xe4\xa8>" + + "d\x9e\xcf\x04f\xca\xb0\x0aH\x91\xf2\x8f/\x83\xbe\x0b" + + "$s\xe1\xbe\xbfd\xd3\xf9\x0a\x99\x0b\x13\x01<\xea\x06" + + "\xf0\xcd\x09\xff\xc2\xdb\x1f\xfaZ\xdf\xef\x1fy\xa0\xfa\x1e" + + "*\xcd\xff\xd5\xf6x\xc6\xf5\x8c\xdc\xd6I\xa0\xee*\x82" + + "\xff\x9d2\xf8\x1f\xd7\xc7&t\xf4\xce!\xcc\xc3\x0a\xc5" + + "\xf4\x901\xd9\xda\xd3\x8d\x92\x8c\xb1(\x84\x9b\xa44y" + + "\x1eO\xc6\x18o\xc3\xfd\xe56\x1e\x95-\xf2d\x0c\xd6" + + "\x89Q\xd9\xb3\x96c2\x06\xf2t7$\xfb\x97c2" + + "F/\xe8\xa6$;6\x11B\xa7&W\x0cT\xa6f" + + "d\x86\x8d!V\x99\x9c1d\xd9\x8b\x96.\xddi\xba" + + "\xc5\x13\xf3\xee\xe2\xf6\xa1b\xa9m\xd9\"\xbfX\xcc-" + + "^\xd2z\xe2\x18\xb6(\x8eA\x0b\xa7\xe4,Z\xda\xd6" + + "\xea\x8b\x96\x1e\xd1\x9c\x1c\xb4[z\xe2\xa2\xc5\x16\xa1[" + + "\xfe\x92P\xb4\x84\x13\xf6B\x87\xf5\x91\xda]\x84d\xe7" + + "j\x1a\xcd.\xd4\xd4t\x04m\x0f!\xd9\x85 _\xa6" + + ")\x0e\xeb\xa5\xda\xad\x84d\x97\x81\xbc[S\x1c\xd6\x1d" + + "\xda\x0b\x84dW\x81|PS\x1c\xd6\xfd\x1aL\x9f\x83" + + " ?[S\x1c\xd6g\xe1y\xce\x06\xb9\xa9)T\x96" + + "\x06\x92\xf9\x8d\x80\xdc\x03y,\xc6\xed\x86mx?^" + + "H\x0a\xd8\xd0\xc0-\xf6s\xb5\x1f\x81I\x0d\xf2\xcb@" + + "\xde\xd8\x88\x03w\xf1\xa5\x9c\x88O2\xf7M\x99\x82\xae" + + "\xb8\xc5\xd7k\xcd\xa0\xb8\x0d\x14\xf7\x82b\xeaT\xee\xb6" + + "\xbe\x07\xef(d\xe8KN\x9b\xc6\xdd\xd6\x0f\xa3\xfcQ" + + "\x90?\x0d\xf2\xa6&\xee\xb6~\x0a\x9f\xeci\x90\xbf\x88" + + "\xac\x89\xd3\xb9\xdb\xfay\x0d\xc9w@~\x00\xe9\x0e\xe3" + + "\"\xfa\x8a=\xf4:\xc8\xdfC:\xc5\x04wg\xbf\x8b" + + "\xe7\x7fO\xd3\xe8\x00\x06_\x93|}\xf9\x08\x1f,\x1a" + + "\xd5h6\x11U\x885\x9a\xa2\xd0A\xd3@>\x0b\x83" + + "\xaf)\\_\x16\xb7D\xe7\xc0s\xcd\x05\xc5B\x8c\xbe" + + "\xa6\xf9\x023?\x0a\x13\xfdB\x90/\xc3\xe8k\x0b\x8f" + + "\xbe.E\xf92\x90w\x83|\xc6\x0c\x1e~\xed\x88>" + + "BH\xb6\x1b\xe4} \x9f9\x93\x87_\xd7F\xaf!" + + "$\xdb\x07\xf2\xcd \x9f5\x8b\x87_7\xe2y6\x83" + + "|\x04\xe4\xb3g\xf3\xf8+\x8b\xc2\x03\x98 \x1f\x03\xf9" + + "\x9c9|a+G\xc12\xdc\x01\xf2\xdd \xff\xd4\xa7" + + "\xf8\xc2v!\xb6\xbf\x04\xe4W\x81\xfc\x88#\xf8\xc2v" + + "E\x14A\x08@~c4B}\xb7<\xa4\x02\xde\xf7" + + "\xba\x99\x0d\x15\xfe@\xb7<\xd4ix\x83\x06-\xb2^" + + "\xf74\xcb\xdeN-\xa9\xd3=f\x9a\x86G\x19\xcc\xb6" + + "\xbd\xeeiq\xcb\xde.\xd5C\x86\xd7\x93/\xb0\xae\x88" + + "m\x0d\x1bN\x91\xe5W:v1k\x14,Ma\x0b" + + "\x13\x1b\xe9<\xdd\x10\x12#\x86\xbaa\xc3b\xeb\x9c." + + "\x9b\xea\x8e\xcb@\x1f\x87\x06\xaa\xb5\xb4\xb5\xcf6,\xd2" + + "\xeeU\xdes\xa0\xa0^\x1fr5\x8e*\x84f\xa6\xee" + + "z\xebKy=\xe21\xb8\x9dncx\x989\x8c'" + + "-W\xb7\xd1x\x9b\xe0\xcej\xb6u=\xc7\xb6\x0a\xbd" + + "\x96\x967\xb8\xed\xb6n\xb8\xcb\xb1]\xb7\xcbv\x98\x09" + + "\x02\xa5\xbf<\xe4v\x84\xdb\x11\xf3H\x1c&\x92\xea\xae" + + "@\x9f\xc2\xe9\xb6\xb7\xde\x8d\xeb\x15\x84n\x86\xd35\xc2" + + "r[i\xaf{:cy\x96\xaf\xa0n\xb3\x87\xe0b" + + "$c!3X5\xa9C\x84\xe9V\x9e9\x9d\xfc\x8d" + + "l\xd0MM\x8d\xc1(\xdc\x0ekug\xeb\x86\xca\xa8" + + "F\xa1\xe4\x0e\xd8e+\x1f\x19\xb0\x87\x0ck`\x0cQ" + + "\x9c\xdd\xca7\x05m@A\xda\xb9JU\xac\xb1\xb7w" + + "\xea\x9a\x95G\x88W\xe5\xf0.\xbb8dX\xaa\xf9[" + + "(\xb9\xab\x8c\xc2H'\xd5E\xeb\xd8\xe9\xe5%\x87\xd4" + + ".\x9b\xa0\x8d\x04\xda\xf5\x961l;Ey\x8f\xc5\xb2" + + "\xe9\x19%\xdd\xa3#\xbd\x16\xbe,\xcdv\x14^\xbc\xfc" + + "j\xbdX\x84}1\xd7\xc6\x1f\x819\xe4" + + "Y\xcc?A\xb3=\xce\xad\xc6\xe3\x90\xb3\xfbX0>" + + "\x17\x81\xbc9!\xe8\xd8\xb4\xd5\x81\x99\x8ffu\x8ar" + + "\xa3\xf1\\4bw\x80|7\x9a\xdbIn4^\x88" + + "rinG\x9b\xb9\xd1x)\x9e\xff\x12\x90_\x85F" + + "u\x8a\x1b\x8dW \x7f\xf6^\x90_\x87Fu\x9a\x1b" + + "\x8d\xfb\xd0x\x0e\xf9\xb3\xfd\xad\xcc\xb1\x98\xd9\xe1\x10\xad" + + "\x10~\x96\xd3j\x02)\xd7\x18\xd2yex\xd1\xb8\x1c" + + "\x94\x01\xee\xbf\xf8\x9e\x83\xe6%9\x00iB\x8eZQ" + + "\xbf\x9f7\x1c\xd5\x1a0\xbc.\xbbX4\x08\xf5\xc2\xe3" + + "\x0b\x86\xd7\xe9\xe8V\x8e\xd0\x91@\xb6\xb3\xa4\xbb\xae1" + + "\xca\xd4\xe3\x06X\xd1\xf6\x08\x95\x911\xfe\x8c\x1b\x18\xc9" + + "T\xde\x8f\xd8)\xf6Q\xc7.1\xc73\x18\x16\xfe_" + + "\xf9\x83/\xcc\xfa\xd5\xc9w\x1e$\x84\x9cB\x934\xd3" + + "\x0f\xb6\xaf\"L\xd2\xcf\xf67P\x8a\xfbi\x8a\x93\x0a" + + "\x15g\x8c`\x8c\xa5\x04S\xd6\xff\xe4DM\xfcD\xbe" + + "\xedN\x9c0rv\xb1\xa8#s\x12\xf9\xff\xc3\x15&" + + "\xa3j\x0d;\x1fg\x1c\xd9\x91C\xb6\xed\x99v\xa1\x17" + + "\x164\xe5\xa5d\x9d\\\x97M\xe2\xc5\xa2\xe1M\x10S" + + "\x90v\xf3\x0c\x93\xea\x09\xae~\x92|\xe5S\xb9\x95\x19" + + "\xa6-W\x94\xf74h\xd1\xc4_\xe37\x94\x9c?G" + + "\x02\xf6'\xe9\\\xdc\xb5`\x86@\x80\xd8\xafy2\x07" + + "m\xd8a\xdbN/\x17\x0f\xc3\x06\xd4%P\xb8xl" + + "@\xf83\xb9\xc5\xc4\xab\xbc\xaaii\x97W\xb0:\x07" + + "\x86\x92\x8e\x06\x88\x04\xe4\x0f&K\x86\xc9\xfa2\xfc\x15" + + "\x15\x86\x92\x81r\x09\xc8_'\x0c%\xa5x\x00}\xa0" + + "\xf5\xc2P\xda\x86r\xe9\x03\x8d\x09C\xa9\x8c\xf7\xa3\x00" + + "\xf5Sn(U\x1bt\x111\xeb\x9e\x87r\xe9\x1bm" + + "l\xe0\xb3\xeeE\x88\xdd~IX\x9c0\xa5\x91\xcf\xba" + + "W\xa0\xef\xf2\xaa\xd0g\x1aXJ\xd7c{,N\xb8" + + "\x83*\xe4\x98\xb7c<.4\xf4\x90\xb8\\~\xac\x19" + + "\xc4A\x08\x0b\x10\xc28\x035\xc2\xffB\xbb\x83\x0e\x87" + + "6\x84]\xf6Je\xc59\xa7{e\xcc9P\xac," + + "<\xf1\x80\xee\xa9d\xe4z\xce+\xeb\xe6\x1a\x9d\xe2;" + + "\xed\xc8\xe54fV\xc1\xca\xe7\xd7P]hc\xb9\xc9" + + "\xb5\xab\x99\xe6l\x0d\xa9\x01\xaa\xad\x96\xda\x16\xc9:\x01" + + "\xff\x15\xa0\x7f\xd9\x85\x9e\xb8\xe59\xe3Ui\x0fs\x94" + + "b\xbc\xc0.\xb9o\x8e\x8cC\x87v\x89\x1a\x86\x0e\x0b" + + "\xfc\x1e;FF\xa1\xc3\xb4\x87'\x8e\x91Y\x13Td" + + "=<\x05\xb2\xc75\xda\xff\xacLYL>\xd3)3" + + ")`\xd3'h\xdc4ON\x0c%\xc7\xb0\x1d\xdc\xcf" + + "\x85\x0cr\xb1\x92\x91\x0f\x9e=\xe6\xa9\xff\xeb\x85p\x96" + + ".r\x9c\x8b\x093\xc0$\xbe\xb3 o H\x1b\x08" + + "8\xeaE\xfd\xd6\x02^\xbf\xc5\xeb$\xf4-\xe82<" + + "\xab\x93\xd7o\x0d\xa1\xcb\xb0\xbf\x8d\xd7ou\xf2\xfa\xad" + + "cx\xfd\xd6\x00\xaf\xdf\x1a $n\xe4M\xd6\xee2" + + "\xdd\xc9\x8d\xf8\xfc\xcf\x06F\xe2\x8e1<\xbeS\xf8\"" + + "|\xcf\xd1s[70\x87\xc4\x8c\xe1\xf1\x0c\xfe\xda\xe9" + + "0\xd7\xd3\x1d/\x96/\xd9\xb0\x17n]Tt;\x09" + + "e\xc1\xff\x1d\x84z\x93<\x9b\x9c\xdd\xb2:O\x03\xf0" + + "\xe0?4MI\xd5 XPk\x10,\xaf5\x08\x1c" + + "u\x10Dj\x0d\x02M\x0c\x82-\xca\x0b\x87\xd9\x05F" + + "\xc13\x9b$\x11DP\x83\x91|\xfe\x06\x19\xa8\xe4\xa9" + + "\xe2\xe2E\xb7\x17,\xd7\x95?\xfdaS/\xb8\x9d\x86" + + "G2\xc3\x063\xf3\xc1\xc4\x1a\xcbYv\xd8\x86\x99\x0c" + + "_\"\x89[\xdd\xac \xe3\x8b\xe7\x18\xc5\xb27\xd2M" + + "4V@\x86\x0c\x0d\xc6\x96\xcb\xcay\xdb\xd1\xa9U`" + + "\x03\xcc5\xf2\xb1\xb2nNHbj\x98\xa4W\x15w" + + "\xab\xe8]\xd5\xc9>\x08o\x8f\x87|c^\xd9\xad\xda" + + "\x0b(q\xbe\xb0\xbf\x8b{\x14\xbb?\xc85\x1a?G" + + "a\x90\x0fr\x8d\xce\xbbA\xa6\xd7U<\xc4\x84-\xb9" + + "\xee8\x06s\xfa\xe8\x88\xee\xa2R\x99\xb0Fts\xb8" + + "k+c\xae\xd3\xb8\xdd\xf26" + + "\xc6\x92\xc3\x98krj\x13\xb7[>\xc0\xcb~\x08\xf2" + + "\x06\xf4\xf0L\xe7vK\x1d\xee\xfeB\xcfOk\xd3+" + + "\xc2\xc5\xd3\x84\xdb\xbc0\xec\x9a\x9c\xbe\x82\xc7\x1e\x92X" + + "N\x10\xba~289\x86\xf5\x0e\xa6\xee\x19^9\xcf" + + "\x94\xf2\x8e03\x07L\x94@\xa6\x9b\x13\xdae\xdc\x8a" + + "t\xf2!\xa6;\x86U\xe03gH\xa4i;\xc69" + + "\xb6\xe5Q4k\xca\x8e\xae\xe5\xa4\x17\xa6\x92Kk\xad" + + "a\xc6L\xc3\xa5u$B\xeb\x08mw\x83l\xa0p" + + "\xd8\xf0\xbd[|\xf4t\x09\x95\x16\x04ZGa\x93\x94" + + "\xd3M\xca\xaf\x92\x1bW\xb2\x18\xc4\x8duP\xa1\xeaV" + + "o\x10\x9f\xa1#\x97#\x19\xd4\x85\x96\xdc\x88\xee\xae4" + + "\xc6&\x04\x09H;\xe3\x99\x91\x87v\xf2Te\x10w" + + "\x98\xcc\xc9xY\xe3\x1c\x959\x93\x9b\x0aG\xb7\xf1\x92" + + "J^\xea\x9d\\@H\xdc\xb2-\x96q\x8b\xbai\xc6" + + "\x8aF>>\\6\xcd\xc3\xae\xdc\x136$\xb1 h" + + ";\x93\xef=\x9a:e\xc6DH\x1d\x1d\xbc\xdcO\x94" + + "\x06\xddQ\xce\x1bC&\xc3T\x16n\x17,\xc4\x079" + + "\x97?H\x99\xdb<\xc5\x01|\x10\xb4\x80\xa2I\x9d\xdb" + + "\x90J\xb3\xa2\xd3\xb6EZJ\x0e" + + "I\x8dy\xde\x08\xb7\xeb\xe6\xaf\x96\xde\x154\x1a`r" + + "j]\xad\x90g\x9a\xba\xeb\x9dVt\x0b*80\xc8" + + "\xfa\xaad\xb5\x9d@\x9f g\x863\xa1\xf5\xcf\x0b\xe7" + + "\x80FL\xfc\x92\x19\x8f\x01\xceK\x12\x8d\x81i\xf8\xe9" + + "\x05\xb9\xc60\x07\xb4\xa01\x10fB\x86\xc8\x0e\xd5\xb8" + + "0\x01\xb2\xc3|L\xf0\x92\xb80\x01\xb2C+^7" + + "\xc4\x85\x09\x91\x1dNB\xa3\xe2\xe4\x009\x82\x8a`U" + + "\x0f\x9a,\x128\"0e6\xa2<\x04\x8e\xa0\x8d\x94" + + "\xfa\x7f\xfd\xe2\xfc\xf2O\xee\x8d\xfd\x9a\xa4\x8a0'\xf9" + + "9\xdbram\xe4\x89\xf4\xbdyB\xe3\xfe\xf6\x86\x9e" + + "\x9bO\xb86v~\xb0b\xab{\xb5 P\xbb\x92\x0a" + + "\xe2\xf7q%\xbb3\xd8\xa3\x90\x98U\x90\xb6G(m" + + "\xb7x\xb5Y\xb5\x02\xf7e\xe8g\x99L\x83uhA" + + "\xa5\xad\xab{}\xb6[UA\x04\xd2\x0d\xcc\xac\xae!" + + "\xadI\xf5:\x19\x9a\xc1\xaa\xed\"\x9f\x06\xf3t\xb3_" + + "\\\xfbO\xf3\x92_x\x84$\x1b\xef\xf77\xb2\x03\xc7" + + "\xde\xd2\xff\xf9\x8fI\xb2\xe9\x1a\xbf\xc3\xf2\x98e\xe9Y" + + "Z.1g\xd4p\xedv^9\x16(\xfa\xa8\xbd\x9d" + + "W]ieW-\x1c\xd8\xa4\xd0\xa1\x06\xfb\x19\x95\x0e" + + "5\xdc\x0e\xde\xd4\xa9\x82,\x89\xed\xe0-\xd0\xf2F\x8d" + + "\xf6\xdf\x01C\xa8\x81ohn_\xae /\xd55\xf2" + + "\x0d\x8d\xca\x9c\xea[\xb6\xe1\xb2>\xe6\x10mm6\xac" + + "\xac\xd6\x0b\xb9.\xcb\x0b]\x98:\x7fp\x1a\x97O\xcd" + + "\xdf}\xbb\xde\x07\xcfB\xe3\xb2\x07\x84b\x8b^\xec\xb5" + + "\xc2a!\xcc\xd2`\x90L\x1e#\x0e\xb6\x15\x1c\x8d\x96" + + "\xf74\xfd\xb0\xff\xb4'\x1f_\xfb\xf7$\xd9\xb8\xdc?" + + "\xe2'/\x0c\xbf\xfd\xc1\xa7\xff\x95$\xeb\x86\xda\xf9m" + + "\x85E\x1c$\xc6,\xaf\xdf\x0c\xbf\xcf\xd7\xb0\x8c\xf5\x00" + + ",\x09\xef\xa8\xa5\xb9oc\xd9\xe8; \xffP-\xcd" + + "\xfd\x00\xdb\x1f\x04yT\xcdt\xa2\xda\x10!\x03\x9aF" + + "\xb3\xd3\xd4D\xa7FL\\j\x00yZMtJj" + + "\xf0\x19\xa6A>WMt:RC\x86\x19-\x88\xd4" + + "4\x88\xef\xf38<\x8f\x8c\xd44\x8a`\xf2\xf1\x98\xa8" + + "\xb5\x08\xe4'k\xc2\x17\x0a{\x8d\x930O\xe8\x14\x90" + + "\xaf\xd1\x84/\x14V\xfc^\xbc\xee\x1a\x90\x9f\xa9\x09_" + + "(\xec5\xd6k\xf7\x13\x92=\x13\xe4yMT\xdb\xc2" + + "^C\xd7~\xa6&^\x81\x9d\xd1\x84yW\x18\xb0\x02" + + "\xf1\x18f3Q\xbe\xd3(c H\xe6c%\"\"" + + "`\xa5\xc142\x06\xf2\x0b@\x9e\x8c\xf0\x80\xd5y\xda" + + "\x0d\x15\x81\xa3\xe6E\xbch\xf7R\x0c@\xc9\xc0Q\xaa" + + "\x95\x17\xed^\x81\x01%\x198J\xb7\xf1\xa2\xdd}Z" + + "[EZW\xac\x89\x1b,\xd7\xe3\xed\xdf\x0c\xf2\xbbA" + + "\xde\xb28M[(M\xdd\x89\xe7\xb9\x03\xe4\x0f\x80|" + + "\xc6\x924\x9dAi\xea>\x0cL\xc9l\xaf\x99\x1a7" + + "X\x1e\xc6\xee\x7f\x08\xe4O\x82|\xd6Rn\xb0<\x81" + + "\xaf\xebq\x90?\x0b\xf2\xd9\x0d\xdc`y\x06\xdb\xcb," + + "\xb09\xd3\xb9\xc1\xf2<\x8c\x12\x99\x05\xe6\x970\xaf\xc7" + + "\xb6H\xbc\xa7\xabg%M\xc8\xa1\x1b`\x06\x8b\x06\xf4" + + "Tf\xe7\x99g\xe40\xb4R\xddj4\xc89\x9a\xec" + + "4a\x83\xd8\xe9\x88\x009\xa9\xbe\x9d\x07ek4\x11" + + "P\xae\x82x\x81\x8d\x1aZ\xcdf\xb6c`v\x10\x02" + + "\xbew\xf5\xac$\x87hC\xda\x0d\xdb\xaa}C\xbaU" + + "(\x9b\xba\xb3\x81\x069K\x99\xc9\xee+@j\x8b\xb0" + + "\xfc:q^~\xd6C\xf6\x14\x0dx\xb85\x96?\xdc" + + "\xc3B\xd3vh[\xbb\xa9\xb8\xd3\x888spbF" + + "k\xb4\x0e\xf7]!mp\xc9\x05\xabk\x1d\xc9\x0c\xab" + + "\xfb\xb1 \xa3=.'6aF\x1dr\xc7\xec\x1bV" + + "\xa9\xec\xb9\xebN#j1\xb4\xa8\xf2^G\xe8i\xa1" + + "0S(\xb9\xebNSJ\x9ak\xf6bOW\x0f\xad" + + "5\x9c\xb8\x91\xe7V\x9cQr\xc8\x84\xe9^\\\x0e\x96" + + "o\xd6\xb0r\xa4\x9da\xc6E\xb8B\xb31\xb4\x94\xc6\x1d\xbd\xd8Vq\x0d" + + "O7\xcd\xa0\xda\xf5\xd0\xc6\xc7\xe9\x02\x99\x9d\x03\xb3\x9f" + + "\xd0m8,\x83\xff\"\x0e&Z]\x1d\xdc\x15r\x12" + + "\xafHn\xe5\x19\xe3\xf3y\xc6\xf8q\x9b\xd0\x15r\xf4" + + "\x90\xf0s\xc4M6\xece\x1c\xa30\xe2\xf9\xae\xe7\xe8" + + "\xf0\x0f!\xc4w\x11\xe4{\x0d#\xda\xb0'~\x0c\x18" + + "$\x06\xcdj\xfb&\xb2\xcc\xca \xe6>\xba&\xe6h" + + "\x7f\xfc\xc1Q\xbf\xd9\x7fC\xe0c\xe5h\xfc\xf1\xc1\xf1" + + "\x12\x9b\x84O>4$\x8f_\xae\x10\xca{\xe3\x987" + + "\x11\x9eN\x18m.\xbe\xd5\xc3\x04\x14\x95\x12u\x87\xd5" + + "\xaa\"\x88\x10\xd2\xda\x14\xa1\x84\xf4\xa75\xda?7\x12" + + "|\xda,\xafU\x1c[\xab\xbe\xfc0\xf1\xb9\xa0\x18W" + + "\x86[\xe2\xde\x09\xd9\x0d\xf0\x8e.\x08\xcd\xbeK5\xd8" + + "~\xed\x86\x85x\xaf\x9a\xe0~9\xdaS\xd2\xc0\x10\xc1" + + "\xac\xea\xcc\x14\x84\xe5D\x173\x1a\x0c\xd2\xc0\x88\x0a\xff" + + "\xcc\x9d\xd8\xfen\x90?\x84v\x9f \xcf\x7f\x10\xdb?" + + "\x00\xf2\xc7\xd1\xee\x8b\xf1o\xfe1Ld\x97\x86D\xac" + + "\x81\xdb}\xd5\x86DC\x9dH\"DyhH\x04." + + "\xe6W\xf14\x07@\xfc\x0e\x9a\x83\xf5\xc2\xc5\x8c\x97}" + + "\x0b\xe4\x07\xd1\x1c\x8c\xf1\xb9\xe3}\xb4\xcb\xde\x01\xf9\x87" + + "\x9a(\xe0\x81\xb9\xe3\x03\xb4\xef\xc2\xec\xf3\xa6:n\xf6" + + "}\xa4\xfd\xaa\"\xfb|z=7\xfb\x9a\xa2H\xc5\x0b" + + "\xf2\xb9\x08-\x16\xe3f\xdf\x91\x984.\x93\xcf\x13\x0d" + + "\xdc\xec\x9b\x1f\x85)e\x1e\xc8\x97`v{#\xcfS" + + "j\xc5do\x99|\xde<\x85\xe7)uD\xff\x93\x90" + + "\xec*\x90\x0fbv\xfbT\x9e\xa7\xd4\x8f\xf23A\x9e" + + "\xc7\xe4\xf6i|\x8a\xd31\x99|\x04\xe4\x1e&\xb77" + + "q?\xd5\xb6(\x98k%\x90\xef\xc0\xe4\xf6\xe9\xdcO" + + "5\x1e}\x81\x90\xec.\x90_\x82\xc9\xedqn\xf6]" + + "\x14\xddS\x91|>+\xc1\xcd\xbe+\xa2\xc8\x9a\x0d\xf2" + + "k1\xb9=\xc9\xcd\xbe\xab\xa3\x03jRzrN\xb3" + + "\xa8\xda\xc2dx\x09Y\xf7\xa9\x14\xf7S\xdd\x8e\xed%" + + "4\xdd\x11i\xee\xa7\xba'zk\x05\xd4\xdc\x91Sy" + + "\xd5\xd6\xc3\xd1-\x15\x90rG\xb5\xf0\xaa\xad'\x10J" + + "MB\xcae\x1ay\xd9\xd6S\x98$/!\xe2\xe6\xae" + + "\xe2e[\xcfG7\xa9Pp\x87\xd9\x9dgz\xad<" + + "\x1b\x0bw\xe8\x01\xb2\x06\x95\xe1o\x1a\x97\xf5\xfab\x1a" + + "\xae\xc2\xdf\x08On\xdb\xf9uC.\xa3\"~\xee\xca" + + "X\xbd\\\xdc\xe3z\x81\xc9CJ\x0e\xcb3\x8f\xe5(" + + "\x07\x8f\x1a\xd5\xa9)\xe7\xe9\xf1\x9c\xc9\xb2\xa6A\xdaK" + + "\x95\x13x\xc9v=8\x8a\xb4\xe3\x04-\xa3\x1d\xc5\x89" + + "\x05\xfe4!\x01\x06$U\x99c0\xe7t\x12\x87\x9d" + + "o\xb8\xe5u\x86\xd7\xd8nx\xae\x9d\xa6\xeeA\xff\x84" + + "\x8bL0\x85E\x94\x09\x08=n1\xd5\x1dW\xab\x15" + + "" + + "J\xde.\x95L\xe6tPa\xdaW\xbf\x14\x8bUC" + + "Y\x042\x1a\xdcP\xdc\xa8\xc0}\x16\x11s\x12\x1f\xd1" + + "\xdd\xd0U\xd5>\\\x89\x9bQ\xd2\x1d\xc3\x1b\xefq\xa8" + + "c;\x02\x8a,\x1c\x8b\xf01\xf4\xe9\x8eA4%\xb7" + + "\xf0\x93Wn\x89T\x02\x8d\xafm#\xe1\xda\xf6\x04z" + + "\xef\x1f\x8d\xc0l\x10\x11\xd1l\x90?\x85\x08\\O\x87" + + "\xd9\xa1\xc2C\x9az\x1e]\x1d/\x82\xfc\xf5\x88@\"" + + "\xd2j\xb8F4\xb1\xb6U\xbbF\xa2\xc2\xe5\xf8A\x04" + + "f\xb9\x0fA\xde\x80k[\x83\xb0g\xd1\x171\x0d\x16" + + "\x99Y\xb8\xb65\xf2\xb5\xad\x05\x17%\xe9\x03\x09\xd6\xb6" + + "#Q.} \x8d\xf5|q;\x0e\x17%Y\x946" + + "e:_\xdc\xaa\x8b\xd2\xa66\xf0\xc5m)\xae\x91K" + + "@~\x0a.n\x1cM)\xb5B\x83U\xa3\x1b\xe4}" + + "\xe8\xeb\xa8\xe7\xab\xdbZ\x94\xcb\xa2\xb4\xe91\xbe\xba\x9d" + + "\x85N\x84<\xc8K\xe8\xech\xe0\xab[\x117\xff\xd2" + + "\x09\x92h\xe4\xab[\x19K\xba\xc2,Y*J\xb7." + + "\xc4\xdb\x94&G\xb0\xb8]\x8erir\x04\x8b\xdb>" + + "|\\\xe9\xd3\x08\x16\xb7\xeb\xd1w!M\x91`q\xbb" + + "\x05/\xab\xf84\x1a\xf9\xe2v\x1f\xca\xa5\xefb\xe6t" + + "\xbe\xb8=\x81\xe7\x91&\xc7\xac8_\xdc\x9e\xc1\xca\xb3" + + "gA\xfe\x0a\xfa4\xe2|q{\x09\xbb\xf3E\x90\xbf" + + "\xae\xfd\x7ff\xd1(\x94\\\xf8\x84<:\xde\xe3\xe0'" + + "\x86 7\xe1\x17\xc6okU\x84a\xbd\x8bh\xc2\xbf" + + "\xc2\xc3,;\xb5\x97\x80\x09s\xfe\xa1V\xa7I\x17\xa1" + + "\xff\xc6\xb4\xfaI\xa7\xe9\xffg\xd3\xef'Z7\xff\xa7" + + "\x93t0\xa7F`JE$w\xdck\x16\x1cM\xdd" + + "rLl$\xe3ZA\x17\xffw&\xf4\xc9\x8c\x89\xda" + + "\x91\xa8>\xce\x9cyBW\xdf\xfa\x0c\xf4:&n)" + + "\x99G\xcb\xd5\xcc\xa3\x88\xc8\x0b\xe4\xc7j\x82\xfe\x00\x96\xb4\xa3Q.\x97\xa2" + + "X4X\x8a\xae\xa9X\x8a\x12u\xc1R4P\xb1\x14" + + "\xcd\xa2\xc1R\x04\x1b\xa1\x93A\xbe\x0a\xe7\xe6\x08_\x8a" + + "zp_\x86\xee\xfb\xcd\xb8\xdd\x9c\xc2\x97\xa2\x8d\xd8>" + + "t\xd3\x07P\xcd:>\xd6f\x10\x8fh\xa2N\x04\x96" + + "\x1c\x86rYN=;\xca\x97\x16\x03w\xa7r\xe5\xaa" + + "\x9f\xce\x97\x962\xee\x8aK \xdf\x81n\xfa8_Z" + + "\xc6\xf1q\xa5\xfb\xbe\xb9\x8e/-\xe7\xe1J\xbd\x0b\xe4" + + "\x97\x04+5\xee\x9b\xd0\xcd-\x97\xba)1\xbe\xb4\\" + + "\x8e\xed/\x03\xf9\xb5\xb8\xd4\x09w\xf9\xd5\xe8\xee\x97K" + + "]4!\xf6M\xd8\x0d\xd7\x82\xfcfM\xa0f\xc0\xbe" + + "\xe9&\x94\xcb%0\xdd\xc8\xf7M\xb7\xe0}*\xee\xfe" + + ")|\x7ft'v\x9b\xb24N\xe5\xfb\xa3\xfb\xf0\xb5" + + "Hw\xff\x9cy\x1c#\xf9a\xbc\xffp\xc9\x0c\xe8Y" + + "\xaap23\xf9>\xdb\xac\x86\x98\xaf\x045\xaaL\xa4" + + "\xdc9Z\x85b$P\x8d\xd6\x12M\x09\xf5K\xa1." + + "\x1d\x9f[\x98\xb3u\xa5\x9e\xf3\x88&s\xd2C\xaaj" + + "\xea1\x0e\xb4\xa2Ra\x98\xba\xc5\xce0\xf2\x1e\xa1r" + + "\xca-\x94\xdcAG\xdf\xc2H&\xe7\xd9\xce8M|" + + "\x9cX\xf4\xbes\xc7\xc7\x97\x08\x04.6ZIZT" + + "MB)\xee\x7f%\xc9\x94=\x05\x13p\xe7h\x97S" + + "\x86E2\xf8\xadW\xfe\x0e\x09u)s:0\xc9^" + + "&\x9e\xc6G\xd7*\x8f9\xda\xc5]\xaeDS\x10\x07" + + "\xf3,\xc7\xcc\x95\xb6C\xe2\x83e\xc7R\x92O\xdd5" + + "l\xd8[Cb\xba\xc5T\xe9\x00:\xd2\xe2kTq" + + "Q/\x89\x8cW\x0962\x9a\xf5t\xc7\x93\xc0Q\x15" + + "?y\xe7n@\xfa\x18\xe9\xdaDa\x97n\x91\x0c\x9a" + + "\x12\xd2h\xb7\x8b\xc5^\xd7-\x13\xa5B\xbb\xc4y%" + + "L\x123\xbcq\x1a\xf7\xaf>\xf7\xd89+~\xb5\xe7" + + "\x17\x81\xb1\xf3\x17\xd4x\xf4\xf5vK\x1cB5\xb7\x00" + + ">\x83(\x85YN\xcd\x93l\xc2\x1c\x02\xe9\x11\x0eb" + + "\x97\xb31'@\xc9-\xd0\x82\xdc\x82M\x95\xb9\x05\xd1" + + " \xb7\xa0\x99\x90\xec\xb1 _\xa4V\xc2\x1e\x8fr\xe9" + + ")\x0e\x82\x97\x0a+\xc52\xb5\x12v)\xde\xa7\xccE" + + "\x08\x92\x0bN\xc2\xf4#IR\x13\x14xt\xd0GT" + + "2\x9a\xaa\xc2\x0c\x8e\xdcjX\x05\xdaa\x15L\xd6\xcd" + + "\x0a\xa4\x0a \x17t\x03\xba\x87\xaaJ\xdc\xda\x1e\xc7Q" + + "\xbf\xa0\x9aU\x1d\x7fQ-Gp\xbd\x88\xb8\x17\x0c\x1c" + + "T\\\xb7\xb6\x83T\x05\xb8T\xf3\xf5\xd6\x84/\xb7\x0e" + + "vq\x12Z'x\xb7\x8d\xb8\xb9\x93e\xbf\xc1\xbbm" + + "B\xb9\xcc\xfd\x0c\xdem\x12\xe5\xb2\x1c8x\xb7-\x91" + + "c*R\xbc\x82w;\x1b\xe5i\x90\xcf\x8d(\xec\x07" + + "G\xa2|\x16\xc8\x8f\xc5T\xab)\xfc\x1d\x1e\x8d\xa9\\" + + "sA\xbe0\"\x1d\x91\xf31cKf\x84%\x1e\xe6" + + "\x0b^+f`-\x02\xf9\xc9\x98\x89&<\x85'\xe1" + + "i$\xb2\xf5\x94)|e\xeb@\xb9D\xb6\x9e\xfe\x08" + + "_\xd9z\xf1\xfc\xb2\x823\xfeC\xbe\x99\xea\xc7\xbd\xa9" + + "\xac\xd4lX\xc8W\xb6\xb3\x10\xd5Yf\x90\xc5f\xf2" + + "\x95\x8d\xe1c\xc9\x0c\xb2\xa9\x09\xeei3\xd0\xde\x90\x95" + + "\x9a\xc9$_I\xb6\xa1\\\xa2U\xc3J\xf8iD\xab" + + "\x1e\x08\xd0\xaa\xf7F\"4\x9e+\x95\x17\x85\xf8\xf4\xb9" + + "R\xb9U\xfd\xd1\xa6\xfeX\x1cB\xda\x17Y\x18\xe6\x88" + + "\x15J\xe5\xf0\xff!]\xba\x13\x86t\xcfc\xcex\x1f" + + "i\xe7\xb8h\xe1>D(\xb2$\xc3#\x87A1K" + + "\xd9\x1dZg\x99\x86\xa5\xceL\xa2m\x17i/;\x0e" + + "\x9c$\xb0\xac\x85b\x03i\xb7MO/0ir\x8f" + + "\xe8N\xc1\xb0\x0a\x13\xe6=!\xa7\xdd!\xce\xad\xd4\x95" + + "\xca\xeb\xb1\xae&\x80p\x0b6\x83\xb1\x92\x1e\xf6Mp" + + "\xc9A\x12g\xc5R\x97\xfcZ\x8bC\x06\xb3\xbcj\xb1" + + "5Zd\x83\xacX\"\xb4\xeb\x93\xc1\x18+\x81\xb9\x95" + + "z\xd9\xf4\x94\x1a\x0b\xc1\xf3\xc3\x036-\x03\x18\xb0I" + + "\x0e\x88\xd8\x8c?\x0c\xad\x07Y\x91\xd0\x12\xff\xbf\x8f9" + + "\x84\x16'#w\xaa\xce\x0c\x0b\xb3q\xb3\xfc}T1" + + "\xa5\x9d\xaff\xf1\x88\xbd\xc1\xf5\x0bje\xf1,8l" + + "\x16\x8f\xa8\xa4\xba\xbdS\xcd\xe2\x89\x88,\x9ec\x94," + + "\x9e\xbf4O+\x88\x00}\xe3\xd2;\xa2\xb3\x1e\xb8:" + + "\xcc\xe7\x09\xd3\xb2\xffp\xf5w\xae\\\xfc\xad_\xff!" + + "(\xa9\x0d\x82\xdb\xc1\xc0\xf5\xec\xed\x13\x12\x8c?\x09\xdb" + + "\xdc\x19\x02`/7\xa20\xce\xf1\x88\xed\xb4\xb0\x0f{" + + ".&\xa4\x7f\x15\x07\x84\x0a\x03X\xfd\x0e!\xfd}\x1a" + + "\xed\xdf\xac\x00\x19n\xdc#\xb0\xa8G\xfe\x9b\xc8\x82\x9c" + + "u\xaf\xd7\xc2\xe2\xbc\x9cgX\xb4p\x18w]\x0d\xb2" + + "\xab\xea2\xd1z\xbe'\x9b\xdf)\xe3p\x94\x03\x88&" + + "\x8f\x1f\"\xa4\x7f\xa1F\xfb\x97E\xe8\xceq};\xac" + + "e\x7fq\x08\xfc\x93\xfa\x0f9\x14\xdeg\x17\xfe\xef\xdf" + + "n\xda8\xed]\x92\xa4s\xb4\xec\x86\x0af\xaa\xe5\x93" + + "0S-\xaf0\x0e\x82H\xd9\xf1\x98\xf4,\x8d\x03\xad" + + "\x81/D\xad\x98x\xb8\x04\xe4\xa7P%R\xb6\x02\x8b" + + "(\x14F:\xb1\xf5\xea\xc5p\xf4*\x90\x0f\xaa\x09\x8c" + + "\xfd\x98<\xdd\x17f*\x06\xc5\x18\x1b\xe9\xad\x15U\xad" + + "\x015\x15\xc3\xeb*Lu\x82\x9aj\x1bBQ\x86U" + + "\xa7\x01\xdc\xc6y\xb0\xf1\x90\xccWr\xb0\x87\xe8\xc4\xe2" + + "+\xa8\xf4\xf3V\x8f\xfd\xc0\xf3\xd4E\xc7s&;\xbd" + + "\\\x1c\xd2\x98S\xed-;\x9d\x96\x8bC\xccY7\xdc" + + "\x1d\xd3\xc7\x95\x10\x85a\x9a\x86\xcbr$n[y\xb7" + + "\"\x11\xb9\x9ab\x00\x81y\x07\x8d\"e\xb5=\x1a\xa0" + + "^\xe90\xca}r\x9d\x86\xa6\xbb\x13\x94\x11\xae\xac\xe5" + + "4\xd2\xdcQ\xb9\x19\x08\x87H\x15rzUy\x17\x1b" + + "*\x17x^}\x15\xaa\xdb\xa6\xaa\xe4\\\x10\xb6nR" + + "\x92s\x91Yu\x90\x8d\x11\xcdk\x95e\xf0R\xd86" + + "\xa1Bs\xd2\xb9~\x95\xeeX\xccU'_1\xdbo" + + "\xe1\xacn\xbcR!\xd9I\x88o\xd9^\x97mY\x02" + + "\xfb\xb3\xdd\xb2\x9d\xa2n\xee\x1c6\x8dRI\xc9\xf7\xfc" + + "\xe4\xd3=\x8e\x17\xa5\xc8\x83#\xc4\x1f\xc7y\xe4\x8e\xe6" + + "\x09\x01\xb3\xe1\xc2\x05\xcbu\xbbF\x8c\x12!\x04\x13\xc8" + + "\x1d\x8by\x84\x90LN\xcf\x8d\xb0\x00\xb9|\x92\x88\xff" + + "Z\xbd$0,\xa7\xbfi\xadnx\xe9\xe5\x9bH\x92" + + "\xb6ez,\xcf\x19W\xb3Z\x82\x92\x0f\x98H\x98\xe5" + + "9\x86J<\x1f\x1eZ\xb3@\x1f\xde\x0f\xb4\xedh\xa0" + + "\xc9\xbac\x92um\xb1\xd3\xd8xf\x83n\x96\xd9\xe1" + + "\xfb\x1f\xff\xed\xd2-^\x96\x8e7\xea\x7f\xa5\xed\x99\xbb" + + "\xfb~\xf9\x10\xa6%\xaca94$H\xbc\xcb\xce\xb3" + + "\xfe|8\xdb\xdc\x8e\x19\xfd\x92}#\x98m\xeeD\xfb" + + "\xea\x0e\x90?\x10Qf\x9b\xfb\xd0\x1e\xbb\x17\xe4\x8fF" + + "d\x9di\xeaa\x94?\x04\xf2'#J\xe9\xd7\x13x" + + "\x9e\xc7A\xfelDV\x9b\xa6\x9eA\xfbP\xc6F\xea" + + "\xeb\xf8l\xf3<\xda\x99\xfbA~ \"j\xd9a\xb6" + + "y\x15c\x1d26\x12li\xde\xc6\xf3\xbc\x05\xf2\x83" + + "AE\x05\xcc6\xef\xa3]*\xd3F\xa7\x08\x87\x11\xd5" + + "\x1c5mt\xaa\xf0\x17U\xa7\x8dN\xab\xe7\xe6s\x12" + + "\xe5\xd2O\x05\xe6sS\x0d?\xd5\xf4\x06\xee/\xaa\xf6" + + "S\xc5\x1b\xb9\xb9=\x1f\x1d\x1c\xf3@\xbe\x04\xfdTi" + + "nn\xb7\xa2#F\xa6\x93&[\xb8\xb9}\x12:n" + + "$\xbe_\xb3&\x02\xf3(\x97i\xa6)\xe1`\xea\xc5" + + "\xebJ\xdc\xbft\x1d7\xc3\xfb\xf1\xba}\xa1_\xabe" + + "*7\xc37\xe2yd\xfa\xe9\x8ci\xdc\xc1\xa4\xa3\\" + + ":\xb0f6q\x07\x93\x81r\x89\x078k:w0" + + "m\xc3\x90L\xe8\xc0j\x1f*\xbb\xeb\x86\x87\xa5\xe1\x8b" + + "?\xbb,B\xa5E\x8d\xd5\xf8g\xe8\x0e\x89[`\xc8" + + "V\x14\xe9\xf7\xe9.\x89W x\x98\xba\xeb\xc1\xc8%" + + "\xd4\xa1q9\xa6C\x04R\xd7\xcbz\xb6CY\x9e\x0f" + + "\xefI\xda`\x9d\xaa0\xa5'oA\xe1Tp\xa6X" + + "\xedv\x0e\xcb1c\x94\xf5P\x8cj\x80\x81\x1d\xac/" + + "\x82\x84\xc9\xa3=\x81J\xd1\xd9\x9en\xc2>8\x83\x1a" + + "\xb9\xbc\x80|pl\x0di\xb7]o\x82b`2\xc5" + + "\xe0X\x17\xd1&\xb6\xae!\\\xb9=Ob\xea\xf1\xb9" + + " \xc1K\x09\x89\xe6tdG\x0d\x88j\x14\xf1p\xbe" + + "\xc7\xd2I\x1c6\x19\xf2}:\xeeD\xf0al{\xba" + + "m\x91X\xafkK`4g\xdb\xa2.\xdd4I\x1c" + + "\xad\xa9\x90#\xc1\xd9\xd6Z[\xdcVC\x9c\xd3\xad." + + "\xdba\x03\x94\xb9\xcc\xc3\x1e\xaf.V9\\]@\x9b" + + "\x98\xb6\xef\xfb\xe6\x11\xf7\xfc\xcdUO\xdf\x85\xb3a\x97" + + "m\x0d\x1b\x85\xb0\x10\xf6p\xc5\xf6\x0b\xd4b{\xb1O" + + "xp\x81BI\x11\xec\x13\x1e^\xa0T\xe0\x8b\x82\x91" + + "\xe4c\x03\x0aOE\xb0Oxj@\x09V\x04\xc5\xf6" + + "\xcfm\x92q\x89\xb8=\xec\xf6\x06\x86r\xbc\xa8\x17z" + + "\xc3]\x82=\xec\xf6\xab\x9a~\x197\x19. \xa4*" + + "\xec=\xe3\xf2\x91\x83ano_\xc3F\xbb\x86\x09-" + + "\xc8h\xb9\xedbt\x89he\xf70}\x1b\x12\xd4\x9c" + + "\xb9q\x93\x0aCX\x05W\xd0\\\xab\x07\x9bk\xf5`" + + "\xf3a{P\xec\xb4\x1e[\xa0`\x18\x04T\x1dO," + + "P\xba\xb5\xfe!\xde\x83O\xb5I`\x03\x1az9\xa5" + + "}E\xcf\x09\xc3*c*\x1d\xd2\xb8\xfa\xe3\x1c\xe5G" + + "\x15\xc9Mm\x13\xacK/2G_\x97\xb7\x8b,&" + + "@<\xe6iQ\x1a\x11>\xc3\xb6\xc0g8W\xadI" + + "<\x129\x0ef\x85f{4d\x9a\x0d\xf9\xa5C\xf3" + + "\x1c!\xb4\xd0\xfcG\x1f\xdd\xd94B\x09\xe1\xeb\xebY" + + "h\xfdWb\xce\xd4!\xe6\xcc\x96\x0al\x99\xc0\x9a7" + + "\xd0\xfa7CN\x84\xc0\x9a\xbf\x10\xc1\xf6$\xfeu`" + + "\xcd+X.UD\xb3w\x05%\xda/\xd2\x08\xcd\xe0" + + "\x0cX\xe5\"\x889v5\x8d,\x9f)\xb3^^\xe1" + + "\x8e\x0b(\x03\x1c\xdb\x9b\xc8\xf1:\xa1dp\x92\xf2\xc0" + + "\xedF\x1e17)w\xf4\xf5\x94c&s\xaa/>" + + "\xa1Q\xbb\x09;\xbb\x09\xbc\xb2\x8e\xad\xe7\x07\x1d\xdd\xa2" + + "\xee\xb0\xed\x14\x07\x1d]\x9b\xf0l\x13\xdbd\xf0\xb9&" + + "\xf3\x92h\x93\x01\xcegN\x80\x8f\xaa\x0a\x83\xe2pd" + + "N\xe1Gt\xd1jB\xfaw\x0b\xc7F\xf0\x11\x85\xe5" + + "I\xf7\xfe?|1\x938\x18\x0e\x85\xc11\xc0\xd7O" + + "GA@V\xb6+[jmW*j\x09\x99^\xca" + + "\xb2\xdc\xff\x8f\xb23\xe6m\x1a\x88\xe2\xf8]\x0du\x97" + + "*\xb8\x12\x0bK$>\x00C\xc60\x04\xa224\"" + + "\xc2T-C'.\xf1\xb91I|\xd1\xc5i\xd5." + + "\xa0J,\x19\x18\x18\x19\xf8\x08\x95\xf8\x0cL\x15\xea\xd8" + + "\x811cG\x90\x10c\x90\xdf\xdd\xf9^\x1c7&\xa3" + + "\xad\xba\xb2.\xf7\xde\x9d\xff\xf7\xde\xff\x97\x87\xa7u\x07" + + "}e,X\xe0w\xe9\xdc\x05\x0cs\xde\xd4`Yx" + + "7\xfd}\xfd\xed\xe9\xdf+\xe2\xd1\xa3\xb9A\x88\x11'" + + "a\xa5\x96\x16_\xecq1u)\x9d\xd3\xcf\xcf\xaf\xde" + + "~\xfd\xf4\x91x\xb3#\xb2a\xf8\x0d\xd7\xe7\xe8\xd9{" + + "\xdai\xe5f\x9a\xb3\xbeHS\xd7\xec\x8d\x8e{\x89/E\x07\x13\x88" + + "x\x98\xa4\xc3D\x1a\x8a\xb5F\x1f\xd8!\xd4z\x08\xd4" + + "W\xef\xca\x88j\x1c\x1b)\xf8\x9bU\x04\x84\xe2\x0f\xb0" + + "\xc3\xc8w\x07,\xd6\x92\x94B\xfa{/Z\x98\xe7\xa6" + + "\x7f\x99vM\xebT\x81\xca\x92i\x98\xb0&R\xa4\xb2" + + "\x1e hX\xf9py\xff\xa6z\xf9\xe3\xbb1\x9e\x83" + + "N\x94\xb2$\xb4\x0eR\xc4^\xfbb\xe0F]X\x1f" + + "\xb6\xe0\xb5<\xc5<\xdf\xae\x13\x92A.\x88\xd3\xed5" + + "N\x00CRR\x07\xd1\xe6C\xa5\xd1\xa1\xa9Z+\x9a" + + "\xaa\x0b5\x10:q\xfc\xdcGs\xd0$\x8eY\x13\x95" + + ";\x98\xd5w\xa1\xdc\xc1\xac\xbe\xb7uT\xee\xb0iH" + + "Y-\x04+\xd1gQ\xde\x9f\xba\xed\xc3\xa8\xc2\xbe\xd4" + + "\xe4\xecJ(\xb9=>e',\x1a\xa4[K\x9a\xdd" + + "{\xdf\x99\x84!\x97\x99\xe1T\x03\xbe\xd4\x83\xecR\x1f" + + "S\x99\xff\x10\xc5L\x9fuf\xf0\x8b\xc6\xb8\xc7\xa4}" + + "bu\xbb\x0a\x94Ch*E%YF\xe4\xefh\xe1" + + "\xd0Gc\xdb\xde\xb1\x93\xcd\"\xd2s,\xf3\xc9\xff-" + + "\x0a\x87c.\x9bB\xf4\x87L\xd2\xbeO\xef\x8c\x84\xbd" + + "\xdd\x0a\xefL\x8eso'\x8b\xd2\xe7\x05J\x9f\xdd\xd1" + + "$\x8d\xb46\xa9\x82\xdc\x85\x8c^\xd9\x90\x83\xa4\x05~" + + "\xde\xe3\xe5H\xdc,\xd9c?1=\xb4\xa8\x85\x16I" + + "@\x8a\xb4\xfe\xf0\x11\x082\xdb-B\\\x11\x86\x8e\x88" + + "\xe7\x81\x88\x93~,N\xb1\x09\xc4\xd6\xba\x90\x1e\xb8c" + + "(<<8\xa8\x9c\x8dTe\x10R\xae\xd3\x00x\xe6" + + "\xd0\xd7/\xd1\xd8\xec=\xc6\xb9CGE\x96;\x0e6" + + "4\x8d\xc6\xe0\x95\xf8\x995\xaa\x1b\xf5\x84=\xe9\xfe\x17" + + "\x00\x00\xff\xffa\xedb\xb9" func RegisterSchema(reg *schemas.Registry) { reg.Register(&schemas.Schema{ diff --git a/mapd_repo/cereal/phone_gps_test.go b/mapd_repo/cereal/phone_gps_test.go new file mode 100644 index 0000000000..3bff234f39 --- /dev/null +++ b/mapd_repo/cereal/phone_gps_test.go @@ -0,0 +1,125 @@ +package cereal + +import ( + "capnproto.org/go/capnp/v3" + "pfeifer.dev/mapd/cereal/custom" + "pfeifer.dev/mapd/cereal/log" + "testing" +) + +func phoneGpsWire(t *testing.T, source, envelope uint64) []byte { + t.Helper() + message, segment, err := capnp.NewMessage(capnp.SingleSegment(nil)) + if err != nil { + t.Fatal(err) + } + event, err := log.NewRootEvent(segment) + if err != nil { + t.Fatal(err) + } + event.SetLogMonoTime(envelope) + event.SetValid(true) + navigation, err := event.NewStarpilotNavigation() + if err != nil { + t.Fatal(err) + } + gps, err := navigation.NewPhoneGps() + if err != nil { + t.Fatal(err) + } + gps.SetSourceMonoTime(source) + gps.SetHasFix(true) + gps.SetLatitude(41) + gps.SetLongitude(-111) + gps.SetAltitude(100) + gps.SetSpeed(12) + gps.SetBearingDeg(90) + gps.SetHorizontalAccuracy(5) + gps.SetVerticalAccuracy(5) + gps.SetBearingAccuracyDeg(10) + gps.SetSpeedAccuracy(1) + raw, err := message.Marshal() + if err != nil { + t.Fatal(err) + } + return raw +} + +func attachPhone(s *GpsSub, mode *string) *[][]byte { + queue := [][]byte{} + s.phoneGps = &Subscriber[custom.StarPilotCarState_Gps]{reader: PhoneGpsReader, maxBytes: 250 * 1024, readBytes: func() []byte { + if len(queue) == 0 { + return nil + } + value := queue[0] + queue = queue[1:] + return value + }} + s.mode = func() string { return *mode } + return &queue +} + +func TestPhoneGpsFollowsTheGalaxySetting(t *testing.T) { + now := uint64(10_000_000_000) + mode := GpsModeBackup + s, internal, _ := testGpsSub(&now) + car := attachCar(s) + phone := attachPhone(s, &mode) + + *phone = append(*phone, phoneGpsWire(t, now-300_000_000, now)) + sample, ok := s.ReadSample() + if !ok || sample.Source != GpsSourcePhone || sample.FixMonoTime != now-300_000_000 || sample.Location.Longitude() != -111 { + t.Fatalf("backup without comma or car GPS: %+v %v", sample, ok) + } + *car = append(*car, carGpsWire(t, now-1, now, true, true)) + if sample, ok = s.ReadSample(); !ok || sample.Source != GpsSourceCar { + t.Fatal("car ranks above the phone in backup") + } + *internal = append(*internal, gpsWire(t, GpsSourceInternal, now, true, true, 1, 2, 5)) + if sample, ok = s.ReadSample(); !ok || sample.Source != GpsSourceInternal { + t.Fatal("comma ranks above the phone in backup") + } + + mode = GpsModePhone + now += gpsModeRefresh + *phone = append(*phone, phoneGpsWire(t, now-100_000_000, now)) + *internal = append(*internal, gpsWire(t, GpsSourceInternal, now, true, true, 1, 2, 5)) + if sample, ok = s.ReadSample(); !ok || sample.Source != GpsSourcePhone { + t.Fatal("prefer phone") + } + now += phoneFixMaxAge + *internal = append(*internal, gpsWire(t, GpsSourceInternal, now, true, true, 1, 2, 5)) + if sample, ok = s.ReadSample(); !ok || sample.Source != GpsSourceInternal { + t.Fatal("prefer phone falls back to comma once the phone fix expires") + } + + mode = GpsModeComma + now += gpsModeRefresh + *phone = append(*phone, phoneGpsWire(t, now, now)) + if sample, ok = s.ReadSample(); !ok || sample.Source != GpsSourceInternal { + t.Fatal("comma and car only keeps comma GPS") + } + now += internalFixMaxAge + 1 + *phone = append(*phone, phoneGpsWire(t, now, now)) + if _, ok = s.ReadSample(); ok { + t.Fatal("comma and car only must never use the phone") + } +} + +func TestPhoneGpsModeIsRereadAtMostOnceASecond(t *testing.T) { + now := uint64(10_000_000_000) + reads := 0 + s, _, _ := testGpsSub(&now) + s.mode = func() string { reads++; return GpsModeBackup } + s.ReadSample() + now += gpsModeRefresh - 1 + s.ReadSample() + if reads != 1 { + t.Fatalf("mode reread early: %d", reads) + } + now++ + s.ReadSample() + if reads != 2 { + t.Fatalf("mode not reread: %d", reads) + } +} diff --git a/mapd_repo/cereal/readers.go b/mapd_repo/cereal/readers.go index 58e0806df3..b85a2fb18b 100644 --- a/mapd_repo/cereal/readers.go +++ b/mapd_repo/cereal/readers.go @@ -45,3 +45,11 @@ func CarGpsReader(evt log.Event) (custom.StarPilotCarState_Gps, error) { } return state.Gps() } + +func PhoneGpsReader(evt log.Event) (custom.StarPilotCarState_Gps, error) { + navigation, err := evt.StarpilotNavigation() + if err != nil { + return custom.StarPilotCarState_Gps{}, err + } + return navigation.PhoneGps() +} diff --git a/mapd_repo/settings/const.go b/mapd_repo/settings/const.go index 9e3218539d..3915177864 100644 --- a/mapd_repo/settings/const.go +++ b/mapd_repo/settings/const.go @@ -61,6 +61,7 @@ var ServiceQueueSize = map[string]int64{ "selfdriveState": QUEUE_SIZE_SMALL, "gpsLocation": QUEUE_SIZE_SMALL, "starpilotCarState": QUEUE_SIZE_SMALL, + "starpilotNavigation": QUEUE_SIZE_MEDIUM, "gpsLocationExternal": QUEUE_SIZE_SMALL, "liveLocationKalman": QUEUE_SIZE_SMALL, "gpsNMEA": QUEUE_SIZE_SMALL, diff --git a/mapd_repo/state.go b/mapd_repo/state.go index b1577907d3..d6f3340379 100644 --- a/mapd_repo/state.go +++ b/mapd_repo/state.go @@ -176,7 +176,7 @@ func (s *State) ProcessGps(sample cereal.GpsSample, success bool, load MapLoader pos := m.PosFromLocation(location) s.Position = pos // Unknown CAN direction or speed uncertainty cannot create confident road evidence. - if sample.Source == cereal.GpsSourceCar && (math.IsNaN(float64(location.BearingAccuracyDeg())) || math.IsInf(float64(location.BearingAccuracyDeg()), 0) || location.BearingAccuracyDeg() <= 0 || location.BearingAccuracyDeg() >= 180 || math.IsNaN(float64(location.SpeedAccuracy())) || math.IsInf(float64(location.SpeedAccuracy()), 0) || location.SpeedAccuracy() >= 100) { + if (sample.Source == cereal.GpsSourceCar || sample.Source == cereal.GpsSourcePhone) && (math.IsNaN(float64(location.BearingAccuracyDeg())) || math.IsInf(float64(location.BearingAccuracyDeg()), 0) || location.BearingAccuracyDeg() <= 0 || location.BearingAccuracyDeg() >= 180 || math.IsNaN(float64(location.SpeedAccuracy())) || math.IsInf(float64(location.SpeedAccuracy()), 0) || location.SpeedAccuracy() >= 100) { s.clearRoadDerived() s.roadFixMonoTime = 0 s.RoadStatus = custom.MapdOut_SampleStatus_noMatch diff --git a/openpilot/cereal/custom.capnp b/openpilot/cereal/custom.capnp index 28ed8ac69f..1480bb6a7e 100644 --- a/openpilot/cereal/custom.capnp +++ b/openpilot/cereal/custom.capnp @@ -90,6 +90,8 @@ struct StarPilotCarControl @0x81c2f05a394cf4af { } version @12 :UInt16; } + + phoneGps @3 :StarPilotCarState.Gps; # sourceMonoTime is comma receive time minus the phone's fix age } struct StarPilotCarParams @0xaedffd8f31e7b55d { alternativeExperience @0 :Int16; diff --git a/openpilot/cereal/gen/cpp/custom.capnp.c++ b/openpilot/cereal/gen/cpp/custom.capnp.c++ index f7b536ea8b..a5d1db5da8 100644 --- a/openpilot/cereal/gen/cpp/custom.capnp.c++ +++ b/openpilot/cereal/gen/cpp/custom.capnp.c++ @@ -5,17 +5,17 @@ namespace capnp { namespace schemas { -static const ::capnp::_::AlignedData<81> b_81c2f05a394cf4af = { +static const ::capnp::_::AlignedData<97> b_81c2f05a394cf4af = { { 0, 0, 0, 0, 5, 0, 6, 0, 175, 244, 76, 57, 90, 240, 194, 129, 13, 0, 0, 0, 1, 0, 0, 0, 89, 10, 85, 29, 102, 186, 38, 181, - 3, 0, 7, 0, 0, 0, 0, 0, + 4, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 10, 1, 0, 0, 37, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 85, 0, 0, 0, 175, 0, 0, 0, + 85, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 117, 115, 116, 111, 109, 46, 99, @@ -37,28 +37,35 @@ static const ::capnp::_::AlignedData<81> b_81c2f05a394cf4af = { 111, 0, 0, 0, 0, 0, 0, 0, 78, 97, 118, 105, 103, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, - 12, 0, 0, 0, 3, 0, 4, 0, + 16, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 69, 0, 0, 0, 90, 0, 0, 0, + 97, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 0, 0, 0, 3, 0, 1, 0, - 80, 0, 0, 0, 2, 0, 1, 0, + 96, 0, 0, 0, 3, 0, 1, 0, + 108, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 77, 0, 0, 0, 146, 0, 0, 0, + 105, 0, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80, 0, 0, 0, 3, 0, 1, 0, - 92, 0, 0, 0, 2, 0, 1, 0, + 108, 0, 0, 0, 3, 0, 1, 0, + 120, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 89, 0, 0, 0, 90, 0, 0, 0, + 117, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 88, 0, 0, 0, 3, 0, 1, 0, - 100, 0, 0, 0, 2, 0, 1, 0, + 116, 0, 0, 0, 3, 0, 1, 0, + 128, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 125, 0, 0, 0, 74, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 124, 0, 0, 0, 3, 0, 1, 0, + 136, 0, 0, 0, 2, 0, 1, 0, 104, 117, 100, 67, 111, 110, 116, 114, 111, 108, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, @@ -84,6 +91,15 @@ static const ::capnp::_::AlignedData<81> b_81c2f05a394cf4af = { 176, 52, 164, 42, 71, 245, 229, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 104, 111, 110, 101, 71, 112, 115, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, + 45, 201, 117, 88, 170, 25, 141, 145, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } @@ -92,14 +108,15 @@ static const ::capnp::_::AlignedData<81> b_81c2f05a394cf4af = { #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_81c2f05a394cf4af[] = { &s_83e5f5472aa434b0, + &s_918d19aa5875c92d, &s_be3bc47cd3284f3e, &s_d28ed59fbe1870aa, }; -static const uint16_t m_81c2f05a394cf4af[] = {0, 2, 1}; -static const uint16_t i_81c2f05a394cf4af[] = {0, 1, 2}; +static const uint16_t m_81c2f05a394cf4af[] = {0, 2, 3, 1}; +static const uint16_t i_81c2f05a394cf4af[] = {0, 1, 2, 3}; const ::capnp::_::RawSchema s_81c2f05a394cf4af = { - 0x81c2f05a394cf4af, b_81c2f05a394cf4af.words, 81, d_81c2f05a394cf4af, m_81c2f05a394cf4af, - 3, 3, i_81c2f05a394cf4af, nullptr, nullptr, { &s_81c2f05a394cf4af, nullptr, nullptr, 0, 0, nullptr }, false + 0x81c2f05a394cf4af, b_81c2f05a394cf4af.words, 97, d_81c2f05a394cf4af, m_81c2f05a394cf4af, + 4, 4, i_81c2f05a394cf4af, nullptr, nullptr, { &s_81c2f05a394cf4af, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<40> b_be3bc47cd3284f3e = { diff --git a/openpilot/cereal/gen/cpp/custom.capnp.h b/openpilot/cereal/gen/cpp/custom.capnp.h index 0092fa9eeb..7294c8e8d6 100644 --- a/openpilot/cereal/gen/cpp/custom.capnp.h +++ b/openpilot/cereal/gen/cpp/custom.capnp.h @@ -440,7 +440,7 @@ struct StarPilotCarControl { struct Navigation; struct _capnpPrivate { - CAPNP_DECLARE_STRUCT_HEADER(81c2f05a394cf4af, 0, 3) + CAPNP_DECLARE_STRUCT_HEADER(81c2f05a394cf4af, 0, 4) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE @@ -1663,6 +1663,9 @@ public: inline bool hasNavigation() const; inline ::cereal::StarPilotCarControl::Navigation::Reader getNavigation() const; + inline bool hasPhoneGps() const; + inline ::cereal::StarPilotCarState::Gps::Reader getPhoneGps() const; + private: ::capnp::_::StructReader _reader; template @@ -1712,6 +1715,13 @@ public: inline void adoptNavigation(::capnp::Orphan< ::cereal::StarPilotCarControl::Navigation>&& value); inline ::capnp::Orphan< ::cereal::StarPilotCarControl::Navigation> disownNavigation(); + inline bool hasPhoneGps(); + inline ::cereal::StarPilotCarState::Gps::Builder getPhoneGps(); + inline void setPhoneGps( ::cereal::StarPilotCarState::Gps::Reader value); + inline ::cereal::StarPilotCarState::Gps::Builder initPhoneGps(); + inline void adoptPhoneGps(::capnp::Orphan< ::cereal::StarPilotCarState::Gps>&& value); + inline ::capnp::Orphan< ::cereal::StarPilotCarState::Gps> disownPhoneGps(); + private: ::capnp::_::StructBuilder _builder; template @@ -1733,6 +1743,7 @@ public: inline ::cereal::StarPilotCarControl::HUDControl::Pipeline getHudControl(); inline ::cereal::StarPilotCarControl::SteeringLimitInfo::Pipeline getSteeringLimitInfo(); inline ::cereal::StarPilotCarControl::Navigation::Pipeline getNavigation(); + inline ::cereal::StarPilotCarState::Gps::Pipeline getPhoneGps(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; @@ -12670,6 +12681,45 @@ inline ::capnp::Orphan< ::cereal::StarPilotCarControl::Navigation> StarPilotCarC ::capnp::bounded<2>() * ::capnp::POINTERS)); } +inline bool StarPilotCarControl::Reader::hasPhoneGps() const { + return !_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline bool StarPilotCarControl::Builder::hasPhoneGps() { + return !_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); +} +inline ::cereal::StarPilotCarState::Gps::Reader StarPilotCarControl::Reader::getPhoneGps() const { + return ::capnp::_::PointerHelpers< ::cereal::StarPilotCarState::Gps>::get(_reader.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline ::cereal::StarPilotCarState::Gps::Builder StarPilotCarControl::Builder::getPhoneGps() { + return ::capnp::_::PointerHelpers< ::cereal::StarPilotCarState::Gps>::get(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +#if !CAPNP_LITE +inline ::cereal::StarPilotCarState::Gps::Pipeline StarPilotCarControl::Pipeline::getPhoneGps() { + return ::cereal::StarPilotCarState::Gps::Pipeline(_typeless.getPointerField(3)); +} +#endif // !CAPNP_LITE +inline void StarPilotCarControl::Builder::setPhoneGps( ::cereal::StarPilotCarState::Gps::Reader value) { + ::capnp::_::PointerHelpers< ::cereal::StarPilotCarState::Gps>::set(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), value); +} +inline ::cereal::StarPilotCarState::Gps::Builder StarPilotCarControl::Builder::initPhoneGps() { + return ::capnp::_::PointerHelpers< ::cereal::StarPilotCarState::Gps>::init(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} +inline void StarPilotCarControl::Builder::adoptPhoneGps( + ::capnp::Orphan< ::cereal::StarPilotCarState::Gps>&& value) { + ::capnp::_::PointerHelpers< ::cereal::StarPilotCarState::Gps>::adopt(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::cereal::StarPilotCarState::Gps> StarPilotCarControl::Builder::disownPhoneGps() { + return ::capnp::_::PointerHelpers< ::cereal::StarPilotCarState::Gps>::disown(_builder.getPointerField( + ::capnp::bounded<3>() * ::capnp::POINTERS)); +} + inline ::cereal::StarPilotCarControl::HUDControl::AudibleAlert StarPilotCarControl::HUDControl::Reader::getAudibleAlert() const { return _reader.getDataField< ::cereal::StarPilotCarControl::HUDControl::AudibleAlert>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); diff --git a/openpilot/common/hardware/comma/agnos.py b/openpilot/common/hardware/comma/agnos.py index 6f73b5bb85..58fda61e35 100755 --- a/openpilot/common/hardware/comma/agnos.py +++ b/openpilot/common/hardware/comma/agnos.py @@ -15,8 +15,24 @@ SPARSE_CHUNK_FMT = struct.Struct('H2xI4x') AGNOS_MANIFEST_FILE = "openpilot/common/hardware/comma/agnos.json" +def phone_uplink_active() -> bool: + try: + from openpilot.starpilot.galaxy.companion import phone_uplink_active as active + except ImportError: + # launch_chffrplus.sh runs this file directly from the old tree before PYTHONPATH is set. + try: + with open('/run/starpilot-companion/status.json') as f: + state = json.load(f) + return state.get('active') is True and 0 <= time.monotonic() - state['updated'] < 15 + except (OSError, ValueError, KeyError, TypeError, AttributeError): + return False + return active() + + class StreamingDecompressor: def __init__(self, url: str) -> None: + if phone_uplink_active(): + raise requests.ConnectionError("AGNOS downloads are disabled on the phone uplink") self.buf = b"" self.req = requests.get(url, stream=True, headers={'Accept-Encoding': 'identity'}, timeout=60) @@ -26,6 +42,9 @@ class StreamingDecompressor: self.sha256 = hashlib.sha256() def read(self, length: int) -> bytes: + if phone_uplink_active(): + self.req.close() + raise requests.ConnectionError("Phone uplink activated; AGNOS download stopped") while len(self.buf) < length and not self.eof: if self.decompressor.needs_input: self.req.raise_for_status() diff --git a/openpilot/common/hardware/comma/modem.py b/openpilot/common/hardware/comma/modem.py index f1b79862b1..74c4781851 100755 --- a/openpilot/common/hardware/comma/modem.py +++ b/openpilot/common/hardware/comma/modem.py @@ -242,6 +242,10 @@ class Modem: return True return self._read_param("GsmRoaming") == "1" + def _is_cellular_disabled(self) -> bool: + # data only: the modem stays registered and the SIM is left alone + return self._read_param("CellularDisabled") == "1" + def _publish_state(self, **kwargs): self.S.update(kwargs) self.S["seconds_since_boot"] = time.monotonic() @@ -387,6 +391,8 @@ class Modem: if reg in ("home", "roaming") and greg in ("home", "roaming"): self._publish_state(registration=reg) + if self._is_cellular_disabled(): + return State.SEARCHING return State.CONNECTING if reg != self.S.get("registration"): @@ -429,6 +435,9 @@ class Modem: if new_roaming != self._roaming_allowed: logging.info(f"roaming changed: {self._roaming_allowed} -> {new_roaming}") return True + if self._is_cellular_disabled(): + logging.info("cellular data disabled") + return True return False def _check_iccid(self, state): diff --git a/openpilot/common/hardware/comma/tests/test_modem_cellular_disabled.py b/openpilot/common/hardware/comma/tests/test_modem_cellular_disabled.py new file mode 100644 index 0000000000..d0584fe5ca --- /dev/null +++ b/openpilot/common/hardware/comma/tests/test_modem_cellular_disabled.py @@ -0,0 +1,33 @@ +from unittest import mock + +from openpilot.common.hardware.comma.modem import Modem, State + + +def _modem(params): + m = Modem() + m._read_param = lambda key: params.get(key, "") # ty: ignore[invalid-assignment] # test double + m._publish_state = lambda **kw: m.S.update(kw) # ty: ignore[invalid-assignment] # test double + m._atv = lambda cmd, pfx: '2,1' if cmd in ("AT+CREG?", "AT+CGREG?") else None # ty: ignore[invalid-assignment] # test double + return m + + +def test_searching_dials_when_enabled(): + assert _modem({})._do_searching() == State.CONNECTING + + +def test_searching_does_not_dial_when_disabled(): + m = _modem({"CellularDisabled": "1"}) + assert m._do_searching() == State.SEARCHING + assert m.S["registration"] == "home" + + +def test_connected_hangs_up_when_disabled(): + params = {} + m = _modem(params) + m._ppp = mock.MagicMock(has_exited=lambda: False) + m._poll = lambda: None + m._roaming_allowed = False # as read during init + with mock.patch("os.path.exists", return_value=True): + assert m._do_connected() == State.CONNECTED + params["CellularDisabled"] = "1" + assert m._do_connected() == State.DISCONNECTING diff --git a/openpilot/common/params_keys.h b/openpilot/common/params_keys.h index ba9fb14432..f8aa8c45b6 100644 --- a/openpilot/common/params_keys.h +++ b/openpilot/common/params_keys.h @@ -181,6 +181,7 @@ inline static std::unordered_map keys = { {"CarParamsCache", {CLEAR_ON_MANAGER_START, BYTES}}, {"CarParamsPersistent", {PERSISTENT, BYTES}}, {"CarParamsPrevRoute", {PERSISTENT, BYTES}}, + {"CellularDisabled", {PERSISTENT, BOOL}}, {"CompletedTrainingVersion", {PERSISTENT, STRING, "0"}}, {"ControlsReady", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, {"CurrentBootlog", {PERSISTENT, STRING}}, diff --git a/openpilot/selfdrive/modeld/modeld.py b/openpilot/selfdrive/modeld/modeld.py index eed072655f..36fabad194 100755 --- a/openpilot/selfdrive/modeld/modeld.py +++ b/openpilot/selfdrive/modeld/modeld.py @@ -411,6 +411,9 @@ def main(demo=False): # the joining model drives as small_model until the big model is ready model = HOOKS.attach(model, small_model, vipc_client_main.width, vipc_client_main.height) jetlink_model = model if model is not small_model else None + if jetlink_model is not None: + from openpilot.starpilot.models.jetlink_status import start_latency_writer + start_latency_writer(jetlink_model) params.put_bool("ChestnutLoading", False) cloudlog.warning(f"models loaded in {time.monotonic() - st:.1f}s, modeld starting") release_compile_pool() diff --git a/openpilot/selfdrive/ui/layouts/settings/developer.py b/openpilot/selfdrive/ui/layouts/settings/developer.py index 1bfae8f845..f9dcae51f1 100644 --- a/openpilot/selfdrive/ui/layouts/settings/developer.py +++ b/openpilot/selfdrive/ui/layouts/settings/developer.py @@ -29,6 +29,10 @@ DESCRIPTIONS = { "Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. " + "Changing this setting will restart openpilot if the car is powered on." ), + 'cellular_disabled': tr_noop( + "Hang up cellular data and don't redial. The modem stays registered and the SIM is untouched. " + + "Remote access over cellular data is unavailable while this is enabled." + ), } @@ -94,6 +98,13 @@ class DeveloperLayout(Widget): ) self._on_enable_ui_debug(self._params.get_bool("ShowDebugInfo")) + self._cellular_disabled_toggle = toggle_item( + lambda: tr("Disable Cellular"), + description=lambda: tr(DESCRIPTIONS["cellular_disabled"]), + initial_state=self._params.get_bool("CellularDisabled"), + callback=self._on_cellular_disabled, + ) + self._scroller = Scroller([ button_item("Arabesque", lambda: tr("OPEN"), callback=on_open_arabesque, enabled=lambda: on_open_arabesque is not None and arabesque_available()), @@ -105,6 +116,7 @@ class DeveloperLayout(Widget): self._lat_maneuver_toggle, self._alpha_long_toggle, self._ui_debug_toggle, + self._cellular_disabled_toggle, ], line_separator=True, spacing=0) # Toggles should be not available to change in onroad state @@ -152,6 +164,7 @@ class DeveloperLayout(Widget): ("LateralManeuverMode", self._lat_maneuver_toggle), ("AlphaLongitudinalEnabled", self._alpha_long_toggle), ("ShowDebugInfo", self._ui_debug_toggle), + ("CellularDisabled", self._cellular_disabled_toggle), ): item.action_item.set_state(self._params.get_bool(key)) @@ -160,6 +173,9 @@ class DeveloperLayout(Widget): gui_app.set_show_touches(state) gui_app.set_show_fps(state) + def _on_cellular_disabled(self, state: bool): + self._params.put_bool("CellularDisabled", state, block=True) + def _on_enable_adb(self, state: bool): self._params.put_bool("AdbEnabled", state, block=True) diff --git a/openpilot/selfdrive/ui/mici/layouts/settings/developer.py b/openpilot/selfdrive/ui/mici/layouts/settings/developer.py index 6aae7d7bd0..7b3a68f55e 100644 --- a/openpilot/selfdrive/ui/mici/layouts/settings/developer.py +++ b/openpilot/selfdrive/ui/mici/layouts/settings/developer.py @@ -107,6 +107,9 @@ class DeveloperLayoutMici(NavScroller): self._debug_mode_toggle = BigParamControl("ui debug mode", "ShowDebugInfo", toggle_callback=lambda checked: (gui_app.set_show_touches(checked), gui_app.set_show_fps(checked)), description="Show touch locations and the UI frame rate.") + self._cellular_off_toggle = BigParamControl("disable cellular", "CellularDisabled", + description="Hang up cellular data and don't redial. The modem stays registered and the " + + "SIM is untouched. Remote access over cellular data is unavailable while this is enabled.") self._scroller.add_widgets([ self._adb_toggle, @@ -117,6 +120,7 @@ class DeveloperLayoutMici(NavScroller): self._alpha_long_toggle, self._debug_mode_toggle, self._navigation_toggle, + self._cellular_off_toggle, ]) # Toggle lists @@ -127,6 +131,7 @@ class DeveloperLayoutMici(NavScroller): ("AlphaLongitudinalEnabled", self._alpha_long_toggle), ("ShowDebugInfo", self._debug_mode_toggle), ("NavigationEnabled", self._navigation_toggle), + ("CellularDisabled", self._cellular_off_toggle), ) onroad_blocked_toggles = (self._adb_toggle, self._joystick_toggle) release_blocked_toggles = (self._joystick_toggle, self._alpha_long_toggle, self._navigation_toggle) diff --git a/openpilot/starpilot/analytics/runtime.py b/openpilot/starpilot/analytics/runtime.py index aca44d5d44..4a57eb7bad 100644 --- a/openpilot/starpilot/analytics/runtime.py +++ b/openpilot/starpilot/analytics/runtime.py @@ -1,17 +1,18 @@ """Optional parked reporting; failures never participate in driving process health.""" from datetime import datetime, UTC import math +import signal import threading import time import re import uuid from typing import Any -from openpilot.starpilot.gps.source import GPS_SOURCES, select_location +from openpilot.starpilot.gps.source import GPS_SERVICES, select_location from openpilot.starpilot.analytics.report import ReportClient, build_payload, fetch_branch_commit SERVICES = ('deviceState', 'carParams', 'carState', 'carControl', 'selfdriveState', - 'modelV2', 'drivingModelData', 'managerState', *GPS_SOURCES) + 'modelV2', 'drivingModelData', 'managerState', *GPS_SERVICES) COUNTERS = ('drives', 'meters', 'seconds', 'current_months_meters', 'total_tracked_seconds', 'total_lateral_seconds', 'total_longitudinal_seconds', 'total_aol_seconds') @@ -247,7 +248,7 @@ class AnalyticsWorker: self.client.close() -def start_optional_worker(): +def build_worker(): from openpilot.common.hardware import COMMA_HARDWARE, HARDWARE if not COMMA_HARDWARE: return None @@ -257,4 +258,19 @@ def start_optional_worker(): metadata = get_build_metadata() return AnalyticsWorker(Params(), messaging.SubMaster(list(SERVICES)), metadata={'branch': metadata.channel, 'device': HARDWARE.get_device_type(), - 'metrics': {'commit': metadata.openpilot.git_commit}}).start() + 'metrics': {'commit': metadata.openpilot.git_commit}}) + + +def main(): + # Own process so the manager's heap stays small when it forks the onroad daemons. + worker = build_worker() + if worker is None: + return + for sig in (signal.SIGINT, signal.SIGTERM): + signal.signal(sig, lambda *_: worker.stop_event.set()) + worker.run() + worker.persist() + + +if __name__ == "__main__": + main() diff --git a/openpilot/starpilot/analytics/tests/test_runtime.py b/openpilot/starpilot/analytics/tests/test_runtime.py index 5c4bdace5b..a71636128e 100644 --- a/openpilot/starpilot/analytics/tests/test_runtime.py +++ b/openpilot/starpilot/analytics/tests/test_runtime.py @@ -113,12 +113,24 @@ def test_startup_onroad_never_contacts_transport(): def test_host_optional_hook_does_not_construct_network_worker(): from unittest.mock import patch - from openpilot.starpilot.analytics.runtime import start_optional_worker + from openpilot.starpilot.analytics.runtime import build_worker with patch('openpilot.common.hardware.COMMA_HARDWARE', False), patch('openpilot.starpilot.analytics.runtime.AnalyticsWorker') as factory: - assert start_optional_worker() is None + assert build_worker() is None factory.assert_not_called() +def test_process_saves_counters_when_stopped(): + from unittest.mock import patch + from openpilot.starpilot.analytics import runtime + obj, values, _source, _clock, client = worker() + values.pop('UsageStatsState', None) + obj.stop_event.set() + with patch.object(runtime, 'build_worker', return_value=obj), patch('signal.signal'): + runtime.main() + assert 'UsageStatsState' in values + client.close.assert_called() + + def test_malformed_saved_state_has_finite_sanitized_counters(): obj, values, source, clock, client = worker() values['UsageStatsState'] = {'version': 1, 'counters': 'bad', 'region': {'latitude': 12.345678}, 'extra': 'x' * 100000} diff --git a/openpilot/starpilot/galaxy/companion.py b/openpilot/starpilot/galaxy/companion.py new file mode 100644 index 0000000000..27779e2973 --- /dev/null +++ b/openpilot/starpilot/galaxy/companion.py @@ -0,0 +1,137 @@ +"""Phone uplink protocol and local-only lease. Safe to import from data guards.""" +from __future__ import annotations + +import ipaddress +import math +import os +from pathlib import Path +import re +import threading +import time + +from openpilot.starpilot.galaxy.hotspot import ADDRESS, NETWORK, atomic_json, bounded_json + +COMPANION_PROTOCOL = 1 +LEASE_SECONDS = 15 +LEASE_PATH = Path('/dev/shm/starpilot-companion.json') +STATUS_PATH = Path('/run/starpilot-companion/status.json') +APK_PATH = Path(__file__).parent / 'bin/starpilot-companion.apk' +UPLOAD_DENY_HOSTS = ['commadataci.blob.core.windows.net', 'commadata2.blob.core.windows.net', + 'upload.comma.ai', 'logs.comma.ai'] + + +def fresh(value, now): + updated = value.get('updated') + return type(updated) in (int, float) and math.isfinite(updated) and 0 <= now - updated < LEASE_SECONDS + + +_status_cache: dict = {} + + +def phone_uplink_active(path=STATUS_PATH, clock=time.monotonic) -> bool: + # Guards call this per upload chunk; re-parse only when the file is replaced (atomic_json renames). + try: + st = os.lstat(path) + key = (st.st_ino, st.st_mtime_ns, st.st_size) + cached = _status_cache.get(str(path)) + if cached is None or cached[0] != key: + state = bounded_json(path) + cached = (key, state.get('active') is True, state) + _status_cache[str(path)] = cached + return cached[1] and fresh(cached[2], clock()) + except (OSError, ValueError, TypeError, AttributeError): + return False + + +def validate_lease(value): + if type(value) is not dict: + raise ValueError('Invalid companion heartbeat') + try: + peer = ipaddress.ip_address(value['peer']) + subnet = ipaddress.ip_network(NETWORK) + if peer not in subnet or peer in (subnet.network_address, subnet.broadcast_address, ipaddress.ip_address(ADDRESS)): + raise ValueError('A Galaxy hotspot peer is required') + if type(value['port']) is not int or not 1024 <= value['port'] <= 65535: + raise ValueError('Invalid SOCKS port') + if type(value['protocol']) is not int or value['protocol'] != COMPANION_PROTOCOL: + raise ValueError('Update the companion app') + for key in ('user', 'pass'): + if type(value[key]) is not str or not re.fullmatch(r'[A-Za-z0-9_-]{16,128}', value[key]): + raise ValueError('Invalid SOCKS credentials') + if type(value['version']) is not str or not re.fullmatch(r'[0-9A-Za-z._-]{1,40}', value['version']): + raise ValueError('Invalid app version') + if type(value.get('bytes', 0)) is not int or not 0 <= value.get('bytes', 0) <= 2**63 - 1: + raise ValueError('Invalid byte counter') + except (KeyError, TypeError) as error: + raise ValueError('Invalid companion heartbeat') from error + return {key: value[key] for key in ('peer', 'port', 'protocol', 'user', 'pass', 'version')} | {'bytes': value.get('bytes', 0)} + + +class CompanionRegistry: + def __init__(self, root=None, lease_path=LEASE_PATH, status_path=STATUS_PATH, clock=time.monotonic): + if root is None: + from openpilot.starpilot.storage import starpilot_storage_root + root = starpilot_storage_root() / 'companion' + self.path = Path(root) / 'settings.json' + self.lease_path, self.status_path, self.clock = lease_path, status_path, clock + self.lock = threading.Lock() + + def enabled(self): + try: + return bounded_json(self.path).get('enabled') is True + except FileNotFoundError: + return False + + def save(self, payload): + if type(payload) is not dict or set(payload) != {'enabled'} or type(payload['enabled']) is not bool: + raise ValueError('Expected enabled boolean') + with self.lock: + atomic_json(self.path, payload) + if not payload['enabled']: + self.lease_path.unlink(missing_ok=True) + return self.snapshot() + + def heartbeat(self, payload, peer, remote=False): + if remote: + raise PermissionError('Phone uplink is only available on the Galaxy hotspot') + if type(payload) is not dict or set(payload) - {'port', 'protocol', 'user', 'pass', 'version', 'bytes'}: + raise ValueError('Invalid heartbeat fields') + lease = validate_lease({**payload, 'peer': peer}) + with self.lock: + previous = self.lease() + # The same hotspot peer may rotate credentials (app restart); only a different phone is refused. + if previous and previous['peer'] != peer: + raise FileExistsError('Another phone is sharing data') + enabled = self.enabled() + if enabled: + atomic_json(self.lease_path, {**lease, 'updated': self.clock()}) + return {'ok': True, 'enabled': enabled, 'active': phone_uplink_active(self.status_path, self.clock), + 'protocol': COMPANION_PROTOCOL, 'uploadDenyHosts': UPLOAD_DENY_HOSTS} + + def lease(self): + try: + value = bounded_json(self.lease_path) + return {**validate_lease(value), 'updated': value['updated']} if fresh(value, self.clock()) else None + except (OSError, ValueError, KeyError, TypeError, AttributeError): + return None + + def snapshot(self): + lease = self.lease() + try: + shipped = APK_PATH.with_suffix('.apk.version').read_text().strip() + except OSError: + shipped = '' + active = phone_uplink_active(self.status_path, self.clock) + reason = '' + try: + runtime = bounded_json(self.status_path) + if fresh(runtime, self.clock()) and runtime.get('state') == 'error': + reason = str(runtime.get('reason', 'Phone uplink unavailable'))[:256] + except (OSError, ValueError, TypeError, AttributeError): + pass + return {'protocol': COMPANION_PROTOCOL, 'enabled': self.enabled(), 'connected': lease is not None, + 'active': active, 'state': 'active' if active else ('error' if reason else 'waiting') if self.enabled() else 'disabled', + 'reason': reason, + 'bytes': lease['bytes'] if lease else 0, 'version': lease['version'] if lease else None, + 'appAvailable': APK_PATH.is_file(), 'shippedVersion': shipped, + 'updateAvailable': bool(lease and shipped and lease['version'] != shipped)} diff --git a/openpilot/starpilot/galaxy/companion_uplink_daemon.py b/openpilot/starpilot/galaxy/companion_uplink_daemon.py new file mode 100644 index 0000000000..f0f15c46d5 --- /dev/null +++ b/openpilot/starpilot/galaxy/companion_uplink_daemon.py @@ -0,0 +1,64 @@ +"""Unprivileged manager process; EOF or expired heartbeats revoke root's lease.""" +import json +import os +import signal +import subprocess +import sys +import threading +import time + +from openpilot.starpilot.galaxy.companion import CompanionRegistry +from openpilot.starpilot.galaxy.hotspot import STATUS_PATH, bounded_json + + +def stop_worker(child): + try: + child.stdin.close() + except OSError: + pass + try: + child.wait(timeout=12) + except subprocess.TimeoutExpired: + pass # The root worker independently expires its pipe lease. + + +def main(): + from openpilot.common.basedir import BASEDIR + from openpilot.common.hardware import PC + if PC or os.environ.get('OPENPILOT_PREFIX'): + raise RuntimeError('Uplink requires the primary comma instance') + registry = CompanionRegistry() + stop = threading.Event() + for sig in (signal.SIGINT, signal.SIGTERM): + signal.signal(sig, lambda *_: stop.set()) + child = None + try: + while not stop.is_set(): + try: + hotspot = bounded_json(STATUS_PATH) + enabled = registry.enabled() and hotspot.get('active') is True and 0 <= time.monotonic() - hotspot['updated'] < 10 + lease = registry.lease() if enabled else None + if child is not None and (not lease or child.poll() is not None): + stop_worker(child) + child = None + if lease and child is None: + child = subprocess.Popen(['sudo', '-n', 'systemd-run', '--quiet', '--pipe', '--wait', '--collect', + '--unit=starpilot-companion-uplink', '--property=TimeoutStopSec=8', + '--property=KillMode=control-group', '--working-directory=' + str(BASEDIR), + sys.executable, '-u', '-m', 'openpilot.starpilot.galaxy.companion_uplink_worker'], + cwd=BASEDIR, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, bufsize=0) + if child is not None: + child.stdin.write(json.dumps({'lease': lease, 'updated': time.monotonic()}).encode() + b'\n') + child.stdin.flush() + except (OSError, ValueError, KeyError, subprocess.SubprocessError): + if child is not None: + stop_worker(child) + child = None + stop.wait(1) + finally: + if child is not None: + stop_worker(child) + + +if __name__ == '__main__': + main() diff --git a/openpilot/starpilot/galaxy/companion_uplink_worker.py b/openpilot/starpilot/galaxy/companion_uplink_worker.py new file mode 100644 index 0000000000..f0e9bc6202 --- /dev/null +++ b/openpilot/starpilot/galaxy/companion_uplink_worker.py @@ -0,0 +1,221 @@ +"""Root, pipe-leased phone uplink. All network changes are runtime-only. + +hev-socks5-tunnel 2.18.0, static Linux ARM64 release. +SHA256: e44a6965cd718d98829f344e9f300a5664d12020557127b7469bee7c8f3098b0 +Policy rules preserve every main-table connected route without modifying modem +or Android Auto profiles, including when a dead modem default route remains. +""" +from __future__ import annotations + +import fcntl +import ipaddress +import json +import os +from pathlib import Path +import select +import signal +import socket +import subprocess +import sys +import time + +from openpilot.starpilot.galaxy.companion import STATUS_PATH, fresh, validate_lease +from openpilot.starpilot.galaxy.hotspot import atomic_json + +INTERFACE = 'spuplink0' +RUNTIME = STATUS_PATH.parent +TABLE = '18082' +BINARY = Path(__file__).parent / 'bin/hev-socks5-tunnel_linux_arm64' +PROBE_INTERVAL = 15 # Re-probe other interfaces only this often unless the routes change. + + +def tunnel_config(lease): + lease = validate_lease(lease) + # JSON is valid YAML; credentials cannot introduce additional configuration. + return json.dumps({'tunnel': {'name': INTERFACE, 'mtu': 1500, 'ipv4': '198.18.0.1'}, + 'socks5': {'address': lease['peer'], 'port': lease['port'], 'udp': 'udp', + 'username': lease['user'], 'password': lease['pass']}, + 'mapdns': {'address': '198.18.0.2', 'port': 53, 'network': '198.19.0.0', + 'netmask': '255.255.0.0', 'cache-size': 10000}}) + + +def command(args, check=True): + return subprocess.run(args, check=check, capture_output=True, text=True, timeout=3) + + +def other_internet(routes, probe=None): + def tcp_probe(interface): + # Numeric probes bypass mapped DNS and bind to the original interface. + for address in ('1.1.1.1', '8.8.8.8'): + try: + with socket.socket() as sock: + sock.settimeout(0.7) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, interface.encode() + b'\0') + sock.connect((address, 443)) + return True + except OSError: + pass + return False + probe = probe or tcp_probe + devices = {r['dev'] for r in routes if r.get('dst', 'default') == 'default' and r.get('dev') not in (None, INTERFACE, 'galaxy0')} + return any(probe(device) for device in sorted(devices)) + + +class Backend: + def __init__(self): + self.child = None + self.owned = False + + def status(self, active, reason=''): + atomic_json(STATUS_PATH, {'active': active, 'updated': time.monotonic(), + 'state': 'active' if active else 'error' if reason else 'waiting', 'reason': reason}, mode=0o644) + + def stop(self): + # Keep the guard active until cleanup succeeds. The ownership marker lets a + # replacement worker recover its own rules after SIGKILL or a tool timeout. + failed = False + + def cleanup(args): + nonlocal failed + try: + command(args, False) + except (OSError, subprocess.SubprocessError): + failed = True + + if self.owned: + cleanup(['ip', 'rule', 'del', 'priority', '18001', 'table', TABLE]) + cleanup(['ip', 'rule', 'del', 'priority', '18000', 'lookup', 'main', 'suppress_prefixlength', '0']) + cleanup(['resolvectl', 'revert', INTERFACE]) + cleanup(['ip', 'route', 'flush', 'table', TABLE]) + if self.child is not None: + self.child.terminate() + try: + self.child.wait(timeout=3) + except subprocess.TimeoutExpired: + self.child.kill() + self.child.wait(timeout=3) + cleanup(['ip', 'link', 'delete', INTERFACE]) + cleanup(['resolvectl', 'flush-caches']) + try: + remaining = json.loads(command(['ip', '-j', 'rule']).stdout) + failed |= any(rule.get('priority') in (18000, 18001) for rule in remaining) + except (OSError, ValueError, subprocess.SubprocessError): + failed = True + self.child = None + if failed: + raise RuntimeError('Uplink cleanup incomplete; worker restart will retry') + self.owned = False + (RUNTIME / 'owned').unlink(missing_ok=True) + self.status(False) + + def start(self, lease, routes): + reserved = ipaddress.ip_network('198.18.0.0/15') + if any(r.get('dst', 'default') != 'default' and r.get('dev') != INTERFACE and + ipaddress.ip_network(r['dst'], strict=False).overlaps(reserved) for r in routes): + raise RuntimeError('Mapped DNS subnet conflicts with an existing route') + if Path('/sys/class/net/' + INTERFACE).exists(): + raise RuntimeError('Tunnel interface already exists') + rules = json.loads(command(['ip', '-j', 'rule']).stdout) + if any(r.get('priority') in (18000, 18001) for r in rules): + raise RuntimeError('Policy routing priorities already in use') + if json.loads(command(['ip', '-j', 'route', 'show', 'table', TABLE], False).stdout or '[]'): + raise RuntimeError('Policy routing table already in use') + config = RUNTIME / 'tunnel.json' + atomic_json(config, json.loads(tunnel_config(lease))) + (RUNTIME / 'owned').touch(mode=0o600) + self.owned = True + self.child = subprocess.Popen([str(BINARY), str(config)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + deadline = time.monotonic() + 3 + while not Path('/sys/class/net/' + INTERFACE).exists(): + if self.child.poll() is not None or time.monotonic() > deadline: + raise RuntimeError('Tunnel failed to start') + time.sleep(0.05) + command(['nmcli', 'device', 'set', INTERFACE, 'managed', 'no']) + command(['ip', 'link', 'set', INTERFACE, 'up']) + command(['ip', 'route', 'add', '198.18.0.0/15', 'dev', INTERFACE]) + command(['ip', 'route', 'add', 'default', 'dev', INTERFACE, 'metric', '2000', 'table', TABLE]) + if 'updated' in lease and not fresh(lease, time.monotonic()): + raise RuntimeError('Phone lease expired during tunnel startup') + # Publish guard before enabling routing so upload loops cannot race activation. + self.status(True) + command(['ip', 'rule', 'add', 'priority', '18000', 'lookup', 'main', 'suppress_prefixlength', '0']) + command(['ip', 'rule', 'add', 'priority', '18001', 'table', TABLE]) + command(['resolvectl', 'dns', INTERFACE, '198.18.0.2']) + command(['resolvectl', 'domain', INTERFACE, '~.']) + command(['resolvectl', 'default-route', INTERFACE, 'yes']) + command(['resolvectl', 'flush-caches']) + + +def main(): + if os.geteuid() != 0: + raise PermissionError('Companion worker requires root') + RUNTIME.mkdir(mode=0o755, parents=True, exist_ok=True) + with (RUNTIME / 'lock').open('w') as lock: + fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB) + backend = Backend() + if (RUNTIME / 'owned').exists(): + backend.owned = True + backend.stop() + stop = False + + def stopped(*_): + nonlocal stop + stop = True + + signal.signal(signal.SIGTERM, stopped) + signal.signal(signal.SIGINT, stopped) + buffer, current, last_input = b'', None, time.monotonic() + message = None + reason = '' + probed_routes, probed_at, has_other = None, 0., False + try: + while not stop: + if not select.select([sys.stdin], [], [], 1)[0]: + if time.monotonic() - last_input > 8 or (message and message.get('lease') and not fresh(message['lease'], time.monotonic())): + break + continue + data = os.read(sys.stdin.fileno(), 8192) + if not data: + break + buffer += data + if len(buffer) > 16384: + break + if b'\n' not in buffer: + if time.monotonic() - last_input > 8: + break + continue + while b'\n' in buffer: + raw, buffer = buffer.split(b'\n', 1) + message = json.loads(raw) + last_input = time.monotonic() + if not fresh(message, time.monotonic()): + break + lease = message.get('lease') + raw_routes = command(['ip', '-j', '-4', 'route', 'show', 'table', 'main']).stdout + routes = json.loads(raw_routes) + usable = lease and Path('/sys/class/net/galaxy0').exists() and fresh(lease, time.monotonic()) + if usable and (raw_routes != probed_routes or time.monotonic() - probed_at > PROBE_INTERVAL): + # Probes to dead default routes can block for seconds; avoid repeating them every heartbeat. + has_other = other_internet(routes) + probed_routes, probed_at = raw_routes, time.monotonic() + usable = usable and not has_other + identity = tuple(validate_lease(lease)[key] for key in ('peer', 'port', 'user', 'pass')) if usable else None + if identity != current or (backend.child and backend.child.poll() is not None): + backend.stop() + current = None + if identity: + backend.start(lease, routes) + current = identity + backend.status(current is not None) + print(json.dumps({'active': current is not None}), flush=True) + except (OSError, ValueError, RuntimeError, subprocess.SubprocessError): + reason = 'Phone internet setup failed. Check the installed tunnel binary and companion service.' + finally: + backend.stop() + if reason: + backend.status(False, reason) + (RUNTIME / 'tunnel.json').unlink(missing_ok=True) + + +if __name__ == '__main__': + main() diff --git a/openpilot/starpilot/galaxy/developer_settings.py b/openpilot/starpilot/galaxy/developer_settings.py index 4cddefb618..241bce56de 100644 --- a/openpilot/starpilot/galaxy/developer_settings.py +++ b/openpilot/starpilot/galaxy/developer_settings.py @@ -8,11 +8,25 @@ from openpilot.starpilot.saved_source import read_saved from openpilot.starpilot.ui.feature_settings_state import FeatureRow, FeatureSettingsState +AA_WIFI_KEY = "AndroidAutoDedicatedWifi" +AA_WIFI_DESCRIPTION = ("Experimental. Join the car's Wi-Fi on a second interface so the comma stays on home Wi-Fi or your " + + "phone hotspot during wireless Android Auto. Applies from the next Android Auto connection.") + + class DeveloperSettingsOwner: - def __init__(self, params, authorized, *, panda_wake=None): + def __init__(self, params, authorized, *, panda_wake=None, android_auto=None): self.params = params self.authorized = authorized self.panda_wake = panda_wake + self.android_auto = android_auto # returns the Android Auto daemon client + + def _android_auto_enabled(self): + if self.android_auto is None: + return None + try: + return bool(self.android_auto().call("status")["status"].get("dedicated_wifi_interface")) + except (OSError, RuntimeError, ValueError, KeyError, TypeError): + return None # the service is off; there is nothing to configure def snapshot(self): raw, readable = read_saved(self.params, KEY, 8) @@ -25,14 +39,32 @@ class DeveloperSettingsOwner: firmware_rows = (() if self.panda_wake is None else tuple(replace(item, vehicle_fingerprint=item.capability[0]) for item in self.panda_wake.rows(parked) if item.key == "IgnoreIgnitionLine")) + enabled = self._android_auto_enabled() + android_auto_rows = () if enabled is None else ( + FeatureRow(AA_WIFI_KEY, "Android Auto: Stay on Wi-Fi", "On" if enabled else "Off", b"1" if enabled else b"0", ("Off", "On"), + available=parked, reason=AA_WIFI_DESCRIPTION if parked else "Park the vehicle to change this setting.", + default_value="On"),) summary = "Changes apply next drive. Panda firmware changes require a device restart." if firmware_rows else "Changes apply next drive." - return FeatureSettingsState("developer", "Developer driving options", summary, (row, *firmware_rows), parked) + return FeatureSettingsState("developer", "Developer driving options", summary, (row, *firmware_rows, *android_auto_rows), parked) def apply(self, request): if request.key == "IgnoreIgnitionLine": return self.panda_wake is not None and self.panda_wake.apply(request) + if request.key == AA_WIFI_KEY: + return self._apply_android_auto(request) if request.key != KEY or request.value not in ("Off", "On") or request.expected not in (None, b"0", b"1"): return False result = commit_exact(self.params, key=KEY, max_bytes=8, raw=b"1" if request.value == "On" else b"0", expected=request.expected, authorized=self.authorized, temp_prefix=".voacc-") return result.committed and result.verified + + def _apply_android_auto(self, request): + enabled, client = self._android_auto_enabled(), self.android_auto + if (enabled is None or client is None or request.value not in ("Off", "On") or request.expected != (b"1" if enabled else b"0") or + not self.authorized()): + return False + try: + client().call("set_dedicated_wifi", enabled=request.value == "On") + except (OSError, RuntimeError, ValueError): + return False + return self._android_auto_enabled() == (request.value == "On") diff --git a/openpilot/starpilot/galaxy/hotspot.py b/openpilot/starpilot/galaxy/hotspot.py index da49b51948..6b7082dd5a 100644 --- a/openpilot/starpilot/galaxy/hotspot.py +++ b/openpilot/starpilot/galaxy/hotspot.py @@ -38,10 +38,11 @@ def validate_config(value): return dict(value) -def atomic_json(path, value): +def atomic_json(path, value, mode=0o600): path.parent.mkdir(parents=True, exist_ok=True, mode=0o700) fd, temporary = tempfile.mkstemp(prefix='.' + path.name, dir=path.parent) try: + os.fchmod(fd, mode) with os.fdopen(fd, 'w') as handle: json.dump(value, handle) handle.flush() diff --git a/openpilot/starpilot/galaxy/hotspot_daemon.py b/openpilot/starpilot/galaxy/hotspot_daemon.py index 54a1bd6f0f..fa179a2ed4 100644 --- a/openpilot/starpilot/galaxy/hotspot_daemon.py +++ b/openpilot/starpilot/galaxy/hotspot_daemon.py @@ -4,15 +4,14 @@ import os import select import signal import subprocess -import sys import threading import time from openpilot.starpilot.galaxy.hotspot import HotspotSettings, STATUS_PATH, atomic_json +from openpilot.starpilot.system.pipe_worker import spawn def main(): - from openpilot.common.basedir import BASEDIR from openpilot.common.hardware import PC if PC or os.environ.get('OPENPILOT_PREFIX'): raise RuntimeError('Hotspot requires the primary comma instance') @@ -36,13 +35,7 @@ def main(): runtime = {'active': False, 'state': 'disabled', 'reason': ''} else: if child is None: - child = subprocess.Popen(['sudo', '-n', 'systemd-run', '--quiet', '--pipe', '--wait', '--collect', - '--unit=starpilot-galaxy-hotspot', '--property=TimeoutStopSec=8', - '--property=KillMode=control-group', '--working-directory=' + str(BASEDIR), - sys.executable, '-u', '-m', - 'openpilot.starpilot.galaxy.hotspot_worker'], cwd=BASEDIR, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, - close_fds=True) + child = spawn('starpilot-galaxy-hotspot', 'openpilot.starpilot.galaxy.hotspot_worker') buffer = b'' last_reply = time.monotonic() runtime = {'active': False, 'state': 'starting', 'reason': 'Starting hotspot service.'} diff --git a/openpilot/starpilot/galaxy/hotspot_netlink.py b/openpilot/starpilot/galaxy/hotspot_netlink.py index 46bd1cfea2..32e4eaafd0 100644 --- a/openpilot/starpilot/galaxy/hotspot_netlink.py +++ b/openpilot/starpilot/galaxy/hotspot_netlink.py @@ -1,4 +1,4 @@ -"""Small nl80211 client for the one Galaxy AP interface; no wlan0 mutations.""" +"""Small nl80211 client for the Galaxy AP and Android Auto car interfaces; no wlan0 mutations.""" import socket import struct @@ -67,12 +67,12 @@ class WirelessInterfaces: 'phy': int.from_bytes(row[1], 'little'), 'type': int.from_bytes(row[5], 'little')} for row in self.query(self.family, 5, dump=True)} # GET_INTERFACE - def create(self, name, primary='wlan0'): + def create(self, name, primary='wlan0', iftype=3): # 3 = AP, 2 = station interfaces = self.interfaces() if name in interfaces or interfaces[primary]['type'] != 2: # station - raise RuntimeError('Hotspot interface exists or primary Wi-Fi is not a client') + raise RuntimeError('Interface exists or primary Wi-Fi is not a client') payload = attribute(1, struct.pack('I', interfaces[primary]['phy'])) - payload += attribute(4, name.encode() + b'\0') + attribute(5, struct.pack('I', 3)) # AP + payload += attribute(4, name.encode() + b'\0') + attribute(5, struct.pack('I', iftype)) self.query(self.family, 7, payload, ack=True) # NEW_INTERFACE def delete(self, name): diff --git a/openpilot/starpilot/galaxy/hotspot_worker.py b/openpilot/starpilot/galaxy/hotspot_worker.py index e8b7f1acf4..2ab6bf15ba 100644 --- a/openpilot/starpilot/galaxy/hotspot_worker.py +++ b/openpilot/starpilot/galaxy/hotspot_worker.py @@ -5,33 +5,40 @@ EOF, ten seconds without a heartbeat, or SIGTERM tears down only our AP. """ from __future__ import annotations -import fcntl import ipaddress import json import os from pathlib import Path import select import shutil -import signal import subprocess import sys import time from openpilot.starpilot.galaxy.hotspot import ADDRESS, INTERFACE, NETWORK, HotspotSettings, validate_config from openpilot.starpilot.galaxy.hotspot_netlink import WirelessInterfaces +from openpilot.starpilot.system.pipe_worker import claim, owned, stop_event ALIAS = 'starpilot-galaxy-hotspot' RUNTIME = Path('/run/starpilot-galaxy-hotspot') STANDALONE_CHANNEL = ('g', 6) +HOLD = 'hold' +# wlan0 first; aa0 is Android Auto's own car link when it runs on a dedicated interface. +STATIONS = ('wlan0', 'aa0') +# Android Auto drops and rejoins the car between attempts; stay put through those gaps. +STANDALONE_SETTLE_S = 30.0 +NEGOTIATING = ('AUTHENTICATING', 'ASSOCIATING', 'ASSOCIATED', '4WAY_HANDSHAKE', 'GROUP_HANDSHAKE') def radio_channel(status): fields = dict(line.split('=', 1) for line in status.splitlines() if '=' in line) # A disconnected station remains available for AA/Wi-Fi association. Do not # depend on an Internet connection to offer local access. Association itself - # gets priority: pause the AP while the station is negotiating its channel. + # gets priority: leave the AP untouched while the station negotiates its channel. if fields.get('wpa_state') in ('DISCONNECTED', 'INACTIVE', 'SCANNING'): return STANDALONE_CHANNEL + if fields.get('wpa_state') in NEGOTIATING: + return HOLD if fields.get('wpa_state') != 'COMPLETED': return None frequency = int(fields.get('freq', '0')) @@ -42,6 +49,32 @@ def radio_channel(status): return None +def band_channel(number): + return ('g' if number <= 14 else 'a'), number + + +def dfs(channel): + return channel[0] == 'a' and 52 <= channel[1] <= 144 + + +def choose_channel(results): + """Pick the AP channel from each station's radio_channel result, wlan0 first.""" + if HOLD in results: + return HOLD + for result in results: + if isinstance(result, tuple) and result != STANDALONE_CHANNEL: + return result + return results[0] if results else None + + +def nm_activating(state): + """NetworkManager device states 40-90 are the steps between disconnected and activated.""" + try: + return 40 <= int(state.strip().split(' ', 1)[0]) < 100 + except ValueError: + return False + + def overlapping_routes(rows): subnet = ipaddress.ip_network(NETWORK) for row in rows: @@ -69,19 +102,48 @@ class HotspotBackend: self.children = [] self.owned = False self.firewall = shutil.which('iptables-legacy') or shutil.which('iptables') + self.connected = set() # channel numbers of the stations that are connected + self.idle = [] # stations that reported no connection; NetworkManager may be about to join one def command(self, args, check=True): return self.run(args, check=check, text=True, capture_output=True, timeout=5) def channel(self): - return radio_channel(self.command(['/usr/sbin/wpa_cli', '-i', 'wlan0', 'status']).stdout) + results, self.connected, self.idle = [], set(), [] + for station in STATIONS: + if station == STATIONS[0]: + result = radio_channel(self.command(['/usr/sbin/wpa_cli', '-i', station, 'status']).stdout) + else: + if not Path(f'/sys/class/net/{station}').exists(): + continue + # Between creation and wpa_supplicant taking it, aa0 has no status yet; that is no reason to drop the AP. + reply = self.command(['/usr/sbin/wpa_cli', '-i', station, 'status'], check=False) + if reply.returncode != 0: + continue + result = radio_channel(reply.stdout) + if result == STANDALONE_CHANNEL: + self.idle.append(station) + elif isinstance(result, tuple): + self.connected.add(result[1]) + results.append(result) + return choose_channel(results) + + def activating(self): + for station in self.idle: + reply = self.command(['nmcli', '-t', '-g', 'GENERAL.STATE', 'device', 'show', station], check=False) + if reply.returncode == 0 and nm_activating(reply.stdout): + return True + return False def alive(self): return self.owned and len(self.children) == 2 and all(child.poll() is None for child in self.children) - def ready(self): + def ap_status(self): + """Whether the AP is up, and its current channel: the driver moves it by itself to follow a station.""" reply = self.command(['/usr/sbin/hostapd_cli', '-p', str(self.root / 'control'), '-i', INTERFACE, 'status'], check=False) - return reply.returncode == 0 and 'state=ENABLED' in reply.stdout.splitlines() + lines = reply.stdout.splitlines() if reply.returncode == 0 else [] + channel = next((line.split('=', 1)[1] for line in lines if line.startswith('channel=')), '') + return {'ready': 'state=ENABLED' in lines, 'channel': int(channel) if channel.isdigit() else None} def _wireless(self, method): client = self.interfaces() @@ -91,10 +153,7 @@ class HotspotBackend: client.close() def stale_owned(self): - try: - return Path(f'/sys/class/net/{INTERFACE}/ifalias').read_text().strip() == ALIAS - except FileNotFoundError: - return False + return owned(INTERFACE, ALIAS) def stop(self): for child in self.children: @@ -157,6 +216,9 @@ class HotspotController: def __init__(self, backend, clock=time.monotonic): self.backend, self.clock = backend, clock self.applied, self.retry_at, self.ready_deadline = None, 0.0, 0.0 + self.station_seen = float('-inf') + self.attempted = None + self.refused = set() # DFS channels hostapd would not start on; use the standalone channel instead def tick(self, config): if not config['enabled']: @@ -165,27 +227,56 @@ class HotspotController: return {'active': False, 'state': 'disabled', 'reason': ''} try: channel = self.backend.channel() + running = self.applied is not None and self.backend.alive() + status = self.backend.ap_status() if running else {'ready': False, 'channel': None} + if running and isinstance(channel, tuple) and self.applied[0] == config: + current = status['channel'] + # The driver moves the AP onto a station's channel by itself; restarting it there would only move it back. + if current is not None and (current == channel[1] or current in self.backend.connected): + channel = band_channel(current) + self.applied = (self.applied[0], channel) + if channel == STANDALONE_CHANNEL: + if self.clock() - self.station_seen < STANDALONE_SETTLE_S: + channel = HOLD + elif channel is not None: + self.station_seen = self.clock() + if isinstance(channel, tuple) and channel[1] in self.refused: + channel = STANDALONE_CHANNEL + if channel != HOLD and (not running or (dict(config), channel) != self.applied) and self.backend.activating(): + self.station_seen = self.clock() + channel = HOLD if channel is None: self.backend.stop() self.applied = None return {'active': False, 'state': 'waiting', 'reason': 'Waiting for Wi-Fi radio readiness or a supported connection channel.'} desired = (dict(config), channel) - if desired != self.applied or not self.backend.alive(): + if channel == HOLD: + # Starting, stopping or moving the AP while a station joins makes the join fail. + if not running or self.applied is None: + return {'active': False, 'state': 'waiting', 'reason': 'Waiting for Wi-Fi to finish connecting.'} + desired = self.applied + channel = desired[1] + if desired != self.applied or not running: self.backend.stop() self.applied = None if self.clock() < self.retry_at: return {'active': False, 'state': 'error', 'reason': 'Hotspot unavailable; retrying shortly.'} self.retry_at = self.clock() + 15 + self.attempted = channel self.backend.start(config, channel) self.applied = desired self.ready_deadline = self.clock() + 15 return {'active': False, 'state': 'starting', 'reason': 'Starting the local Wi-Fi network.', 'channel': channel[1]} - if not self.backend.ready(): + if not status['ready']: if self.clock() >= self.ready_deadline: raise RuntimeError('Hotspot did not become ready') return {'active': False, 'state': 'starting', 'reason': 'Waiting for the Wi-Fi access point.', 'channel': channel[1]} + self.attempted = None return {'active': True, 'state': 'active', 'reason': '', 'channel': channel[1]} except (OSError, RuntimeError, ValueError, KeyError, subprocess.SubprocessError): + if self.attempted is not None and dfs(self.attempted): + self.refused.add(self.attempted[1]) + self.attempted = None self.backend.stop() self.applied = None self.retry_at = self.clock() + 15 @@ -193,26 +284,14 @@ class HotspotController: def main(): - if os.geteuid() != 0: - raise RuntimeError('Hotspot worker requires network administration privileges') - os.umask(0o077) - RUNTIME.mkdir(mode=0o700, exist_ok=True) - if RUNTIME.is_symlink() or RUNTIME.stat().st_uid != 0: - raise RuntimeError('Unsafe hotspot runtime directory') - fd = os.open(RUNTIME / 'lock', os.O_CREAT | os.O_RDWR | os.O_NOFOLLOW, 0o600) - fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + fd = claim(RUNTIME, 'Hotspot worker') backend = HotspotBackend() controller = HotspotController(backend) - stopped = False - def stop(*_): - nonlocal stopped - stopped = True - signal.signal(signal.SIGTERM, stop) - signal.signal(signal.SIGINT, stop) + stop = stop_event() config, buffer, last = None, b'', time.monotonic() try: backend.stop() # clean an interface explicitly marked as ours after a crash - while not stopped and time.monotonic() - last < 10: + while not stop.is_set() and time.monotonic() - last < 10: if select.select([sys.stdin], [], [], 2)[0]: data = os.read(sys.stdin.fileno(), 4097) if not data: diff --git a/openpilot/starpilot/galaxy/http_server.py b/openpilot/starpilot/galaxy/http_server.py index 4e3150536a..4051f5f824 100644 --- a/openpilot/starpilot/galaxy/http_server.py +++ b/openpilot/starpilot/galaxy/http_server.py @@ -107,6 +107,16 @@ def direct_local_connection(peer: str, destination: str, headers) -> bool: return False +def install_origin_allowed(peer: str, destination: str, headers, remote_transport: bool = False) -> bool: + """Large installs are for the tunnel or a real LAN/hotspot client, never the phone Bluetooth bridge (loopback).""" + if remote_transport: + return True + try: + return not ip_address(peer).is_loopback and direct_local_connection(peer, destination, headers) + except ValueError: + return False + + def allowed_authority(host: str, local_address: str, port: int) -> bool: """Accept only the literal address reached by this socket, or loopback's name.""" if host == f'localhost:{port}' and local_address == '127.0.0.1': diff --git a/openpilot/starpilot/galaxy/settings.py b/openpilot/starpilot/galaxy/settings.py index b4e68d9496..4ef7f05f36 100644 --- a/openpilot/starpilot/galaxy/settings.py +++ b/openpilot/starpilot/galaxy/settings.py @@ -452,10 +452,11 @@ def _question(row: FeatureRow, request: FeatureSettingsRequest) -> str: class SettingsGateway: - def __init__(self, params, context: ContextSource | None = None, *, clock=time.monotonic): + def __init__(self, params, context: ContextSource | None = None, *, clock=time.monotonic, android_auto=None): self.params = params self.context = context if context is not None else LiveContextSource(params) self.clock = clock + self.android_auto = android_auto self.lock = threading.Lock() self.views: dict[str, _View] = {} self.intents: dict[str, _Intent] = {} @@ -569,7 +570,8 @@ class SettingsGateway: fresh = self.context.sample() if live else ctx return bool(fresh.parked and not fresh.editing_saved_vehicle and fresh.cp_raw == ctx.cp_raw) return DeveloperSettingsOwner(self.params, authorized, - panda_wake=self._owner(ctx, live=live, session_valid=session_valid).panda_wake) + panda_wake=self._owner(ctx, live=live, session_valid=session_valid).panda_wake, + android_auto=self.android_auto) def _state(self, page: str, ctx: AuthorityContext): if page == "developer": diff --git a/openpilot/starpilot/galaxy/tests/test_companion.py b/openpilot/starpilot/galaxy/tests/test_companion.py new file mode 100644 index 0000000000..8468a826d4 --- /dev/null +++ b/openpilot/starpilot/galaxy/tests/test_companion.py @@ -0,0 +1,126 @@ +import json +import stat + +import pytest + +from openpilot.starpilot.galaxy.companion import CompanionRegistry, phone_uplink_active, validate_lease +from openpilot.starpilot.galaxy.companion_uplink_worker import other_internet, tunnel_config +from openpilot.starpilot.galaxy.hotspot import atomic_json + +PAYLOAD = {'port': 1080, 'user': 'a' * 32, 'pass': 'b' * 32, 'version': '1.0.0', 'protocol': 1, 'bytes': 100} +PEER = '172.31.254.10' + + +def registry(tmp_path, now=lambda: 100): + return CompanionRegistry(tmp_path, tmp_path / 'lease', tmp_path / 'status', clock=now) + + +def test_opt_in_and_stale_lease(tmp_path): + now = [100] + owner = registry(tmp_path, lambda: now[0]) + assert not owner.heartbeat(PAYLOAD, PEER)['enabled'] + assert owner.lease() is None + owner.save({'enabled': True}) + assert owner.heartbeat(PAYLOAD, PEER)['enabled'] + assert stat.S_IMODE(owner.lease_path.stat().st_mode) == 0o600 + assert owner.snapshot()['connected'] + assert 'pass' not in owner.snapshot() + now[0] = 115 + assert owner.lease() is None + now[0] = 99 + assert owner.lease() is None + + +@pytest.mark.parametrize('peer', ['127.0.0.1', '192.168.1.2', '172.31.254.1', '172.31.254.0', '172.31.254.255', '::ffff:172.31.254.10']) +def test_only_hotspot_peers(tmp_path, peer): + with pytest.raises(ValueError): + registry(tmp_path).heartbeat(PAYLOAD, peer) + + +def test_remote_and_conflict_and_disable(tmp_path): + owner = registry(tmp_path) + owner.save({'enabled': True}) + with pytest.raises(PermissionError): + owner.heartbeat(PAYLOAD, PEER, remote=True) + owner.heartbeat(PAYLOAD, PEER) + with pytest.raises(FileExistsError): + owner.heartbeat(PAYLOAD, '172.31.254.11') + owner.heartbeat({**PAYLOAD, 'user': 'c' * 32}, PEER) + assert owner.lease()['user'] == 'c' * 32 + owner.save({'enabled': False}) + assert owner.lease() is None + + +@pytest.mark.parametrize('patch', [{'port': True}, {'port': 22}, {'protocol': 2}, {'user': 'a\n' * 20}, {'bytes': -1}, {'bytes': True}, {'version': None}]) +def test_invalid_payload(patch): + with pytest.raises(ValueError): + validate_lease({**PAYLOAD, 'peer': PEER, **patch}) + + +def test_route_guard(tmp_path): + path = tmp_path / 'status' + assert not phone_uplink_active(path, lambda: 100) + for state, expected in [({'active': True, 'updated': 99}, True), ({'active': False, 'updated': 99}, False), + ({'active': True, 'updated': 85}, False), ({'active': True, 'updated': 101}, False), + ({'active': True, 'updated': float('nan')}, False)]: + atomic_json(path, state) + assert phone_uplink_active(path, lambda: 100) is expected + + +def test_tunnel_mapped_dns_and_interface_probes(): + config = json.loads(tunnel_config({**PAYLOAD, 'peer': PEER})) + assert config['socks5']['address'] == PEER + assert config['socks5']['udp'] == 'udp' + assert config['mapdns']['network'] == '198.19.0.0' + routes = [{'dst': 'default', 'dev': 'ppp0'}, {'dst': 'default', 'dev': 'spuplink0'}, {'dst': '172.31.254.0/24', 'dev': 'galaxy0'}] + calls = [] + assert other_internet(routes, lambda interface: calls.append(interface) or True) + assert calls == ['ppp0'] + assert not other_internet(routes, lambda _: False) + + +def test_backend_routing_and_cleanup_order(tmp_path, monkeypatch): + from unittest.mock import Mock + from openpilot.starpilot.galaxy import companion_uplink_worker as worker + monkeypatch.setattr(worker, 'RUNTIME', tmp_path) + monkeypatch.setattr(worker, 'STATUS_PATH', tmp_path / 'status') + child = Mock() + child.poll.return_value = None + created = [False] + calls = [] + original_exists = worker.Path.exists + + def exists(path): + return created[0] if str(path) == '/sys/class/net/spuplink0' else original_exists(path) + + def spawn(*args, **kwargs): + created[0] = True + return child + + def command(args, check=True): + calls.append((args, phone_uplink_active(tmp_path / 'status'))) + return Mock(stdout='[]', returncode=0) + + monkeypatch.setattr(worker.Path, 'exists', exists) + monkeypatch.setattr(worker.subprocess, 'Popen', spawn) + monkeypatch.setattr(worker, 'command', command) + backend = worker.Backend() + backend.start({**PAYLOAD, 'peer': PEER}, []) + activation = next(i for i, (args, _) in enumerate(calls) if args[:4] == ['ip', 'rule', 'add', 'priority'] and '18001' in args) + assert calls[activation][1] # Data guard is published before route activation. + assert (tmp_path / 'owned').exists() + assert all('ppp0' not in args and 'wlan0' not in args for args, _ in calls) + backend.stop() + assert not phone_uplink_active(tmp_path / 'status') + assert not (tmp_path / 'owned').exists() + child.terminate.assert_called_once() + teardown = [args for args, _ in calls[activation + 1:]] + assert teardown.index(['resolvectl', 'revert', 'spuplink0']) < teardown.index(['ip', 'link', 'delete', 'spuplink0']) + + +def test_backend_refuses_route_collision(tmp_path, monkeypatch): + from openpilot.starpilot.galaxy import companion_uplink_worker as worker + monkeypatch.setattr(worker, 'RUNTIME', tmp_path) + with pytest.raises(RuntimeError, match='conflicts'): + worker.Backend().start({**PAYLOAD, 'peer': PEER}, [{'dst': '198.19.0.0/24', 'dev': 'wlan0'}]) + assert not (tmp_path / 'owned').exists() diff --git a/openpilot/starpilot/galaxy/tests/test_companion_data_guards.py b/openpilot/starpilot/galaxy/tests/test_companion_data_guards.py new file mode 100644 index 0000000000..0595f23a32 --- /dev/null +++ b/openpilot/starpilot/galaxy/tests/test_companion_data_guards.py @@ -0,0 +1,70 @@ +import threading +from types import SimpleNamespace +from unittest.mock import Mock, patch + +import pytest + +from openpilot.system.loggerd import uploader +from openpilot.system.athena import athenad +from openpilot.starpilot.software import fast_update + + +def test_uploader_ignores_unmetered_override(): + instance = uploader.Uploader.__new__(uploader.Uploader) + instance.params = Mock() + instance.params.get_bool.return_value = True # AlwaysAllowUploads + instance.next_file_to_upload = Mock(side_effect=AssertionError('must not select upload')) + with patch.object(uploader, 'phone_uplink_active', return_value=True): + assert instance.step(uploader.NetworkType.wifi, False) is None + with pytest.raises(uploader.requests.ConnectionError, match='Phone uplink'): + instance.do_upload('qlog', '/not-read') + instance.next_file_to_upload.assert_not_called() + + +def test_athena_allow_cellular_is_still_deferred(): + stop = threading.Event() + item = athenad.UploadItem(path='/unused', url='https://upload.test', headers={}, created_at=int(athenad.datetime.now().timestamp() * 1000), + id='phone-test', allow_cellular=True) + queue = Mock() + queue.get.return_value = item + sm = Mock() + sm.__getitem__ = Mock(return_value=SimpleNamespace(networkMetered=False, networkType=SimpleNamespace(raw=1))) + with patch.object(athenad, 'upload_queue', queue), patch.object(athenad.messaging, 'SubMaster', return_value=sm), \ + patch.object(athenad, 'phone_uplink_active', return_value=True), \ + patch.object(athenad, 'retry_upload', side_effect=lambda *_: stop.set()) as retry, \ + patch.object(athenad, '_do_upload') as upload: + athenad.upload_handler(stop) + retry.assert_called_once_with(threading.get_ident(), stop, False) + upload.assert_not_called() + with pytest.raises(athenad.AbortTransferException): + athenad.cb(sm, item, 0, stop, 100, 1) + + +def test_update_fetch_rejected_and_inflight_process_stopped(tmp_path): + with patch.object(fast_update, 'phone_uplink_active', return_value=True), patch.object(fast_update.subprocess, 'Popen') as spawn: + with pytest.raises(fast_update.FastUpdateError, match='disabled'): + fast_update.run(['git', 'fetch'], tmp_path) + spawn.assert_not_called() + # Exercise cancellation of a real process when a link changes mid-fetch. + # Mac disallows killpg(pid, 0) after exit; use a portable child reaper here. + def reap(process): + process.terminate() + process.wait(timeout=2) + with patch.object(fast_update, 'phone_uplink_active', side_effect=[False, False, True]), \ + patch.object(fast_update, '_stop_process', side_effect=reap) as stop: + with pytest.raises(fast_update.FastUpdateError, match='stopped'): + fast_update.run(['python3', '-c', 'import time; time.sleep(20)', 'fetch'], tmp_path, timeout=5) + stop.assert_called_once() + + +def test_agnos_stream_never_starts_or_continues_over_phone(): + from openpilot.common.hardware.comma import agnos + with patch.object(agnos, 'phone_uplink_active', return_value=True), patch.object(agnos.requests, 'get') as request: + with pytest.raises(agnos.requests.ConnectionError, match='disabled'): + agnos.StreamingDecompressor('https://example.test/image') + request.assert_not_called() + stream = agnos.StreamingDecompressor.__new__(agnos.StreamingDecompressor) + stream.req = Mock() + with pytest.raises(agnos.requests.ConnectionError, match='stopped'): + stream.read(1024) + stream.req.close.assert_called_once() diff --git a/openpilot/starpilot/galaxy/tests/test_developer_settings.py b/openpilot/starpilot/galaxy/tests/test_developer_settings.py index 0129b834b8..e903cfb3ae 100644 --- a/openpilot/starpilot/galaxy/tests/test_developer_settings.py +++ b/openpilot/starpilot/galaxy/tests/test_developer_settings.py @@ -7,7 +7,7 @@ from typing import cast import tempfile import unittest -from openpilot.starpilot.galaxy.developer_settings import DeveloperSettingsOwner +from openpilot.starpilot.galaxy.developer_settings import AA_WIFI_KEY, DeveloperSettingsOwner from openpilot.starpilot.galaxy.settings import AuthorityContext, ContextSource, SettingsChanged, SettingsGateway from openpilot.starpilot.longitudinal.voacc import KEY, selected from openpilot.starpilot.ui.feature_settings_state import FeatureSettingsRequest @@ -22,6 +22,19 @@ class FileParams: return str(self.root / key) +class FakeAndroidAuto: + def __init__(self, enabled=False, running=True): + self.enabled, self.running = enabled, running + + def call(self, command, **payload): + if not self.running: + raise RuntimeError("Android Auto service is not running (turn on Bluetooth)") + if command == "set_dedicated_wifi": + self.enabled = payload["enabled"] + return {"ok": True} + return {"ok": True, "status": {"dedicated_wifi_interface": self.enabled}} + + class DeveloperSettingsTest(unittest.TestCase): def setUp(self): directory = tempfile.TemporaryDirectory() @@ -107,3 +120,23 @@ class DeveloperSettingsTest(unittest.TestCase): intent = preview("On") with self.assertRaises(SettingsChanged): gateway.confirm(intent, token, generation, session_valid=lambda: False) + + def test_android_auto_stay_on_wifi_toggle(self): + self.assertNotIn(AA_WIFI_KEY, [row.key for row in self.owner.snapshot().rows]) + service = FakeAndroidAuto() + owner = DeveloperSettingsOwner(self.params, lambda: self.parked, android_auto=lambda: service) + row = next(row for row in owner.snapshot().rows if row.key == AA_WIFI_KEY) + self.assertEqual((row.value, row.choices, row.available), ("Off", ("Off", "On"), True)) + self.assertTrue(owner.apply(FeatureSettingsRequest(AA_WIFI_KEY, row.source, "On"))) + self.assertTrue(service.enabled) + self.assertFalse(owner.apply(FeatureSettingsRequest(AA_WIFI_KEY, row.source, "Off"))) # stale view + self.assertFalse(owner.apply(FeatureSettingsRequest(AA_WIFI_KEY, b"1", "maybe"))) + self.parked = False + self.assertFalse(next(row for row in owner.snapshot().rows if row.key == AA_WIFI_KEY).available) + self.assertFalse(owner.apply(FeatureSettingsRequest(AA_WIFI_KEY, b"1", "Off"))) + self.parked = True + self.assertTrue(owner.apply(FeatureSettingsRequest(AA_WIFI_KEY, b"1", "Off"))) + self.assertFalse(service.enabled) + service.running = False + self.assertNotIn(AA_WIFI_KEY, [row.key for row in owner.snapshot().rows]) + self.assertFalse(owner.apply(FeatureSettingsRequest(AA_WIFI_KEY, b"0", "On"))) diff --git a/openpilot/starpilot/galaxy/tests/test_hotspot.mjs b/openpilot/starpilot/galaxy/tests/test_hotspot.mjs index 5e7aeb785b..9c6fe88882 100644 --- a/openpilot/starpilot/galaxy/tests/test_hotspot.mjs +++ b/openpilot/starpilot/galaxy/tests/test_hotspot.mjs @@ -44,4 +44,26 @@ await vm.refresh() assert.equal(auth, 1) assert.equal(vm.active, false) assert.equal(vm.timer, null) + +const failing = instance() +Object.defineProperty(failing, 'passwordValid', { get: () => GalaxyHotspot.computed.passwordValid.call(failing) }) +failing.adopt({ ...value, config: { ...value.config, enabled: false } }) +failing.draft.password = 'short' +assert.equal(failing.passwordValid, false) +failing.draft.password = 'a’curly-quote-pass' +assert.equal(failing.passwordValid, false) +failing.draft.password = '' +assert.equal(failing.passwordValid, true) +failing.draft.password = 'twelve-chars!' +assert.equal(failing.passwordValid, true) +failing.active = true +globalThis.fetch = async (_url, options) => options?.method === 'POST' + ? { ok: false, status: 400, json: async () => ({ error: 'Use a 12–63 character password' }) } + : { ok: true, json: async () => value } +await failing.save() +assert.match(failing.saveError, /12–63 character password/) +clearTimeout(failing.timer) +await failing.refresh() +assert.match(failing.saveError, /12–63 character password/, 'a poll must not hide a failed save') +failing.stop() console.log('Hotspot: schema, Vue template, preview exclusion, stale drafts, unmount race, credential clearing and authentication passed') diff --git a/openpilot/starpilot/galaxy/tests/test_hotspot.py b/openpilot/starpilot/galaxy/tests/test_hotspot.py index fd31181659..aca69afc4c 100644 --- a/openpilot/starpilot/galaxy/tests/test_hotspot.py +++ b/openpilot/starpilot/galaxy/tests/test_hotspot.py @@ -1,17 +1,29 @@ import json import stat +import struct +from pathlib import Path from unittest.mock import Mock import pytest from openpilot.starpilot.galaxy.hotspot import DEFAULT, HotspotSettings, atomic_json, hotspot_name, validate_config from openpilot.starpilot.galaxy.hotspot_netlink import WirelessInterfaces, attribute, attributes -from openpilot.starpilot.galaxy.hotspot_worker import HotspotBackend, HotspotController, hostapd_config, overlapping_routes, radio_channel +from openpilot.starpilot.galaxy.hotspot_worker import (HOLD, STANDALONE_SETTLE_S, HotspotBackend, HotspotController, choose_channel, + hostapd_config, nm_activating, overlapping_routes, radio_channel) CONFIG = {'enabled': True, 'ssid': 'TheGalaxy-6b86', 'password': '1234567890123456'} DONGLE = 'b0c4a280b2f96b86' +def backend_mock(ready=True, ap_channel=None): + backend = Mock() + backend.alive.return_value = True + backend.ap_status.return_value = {'ready': ready, 'channel': ap_channel} + backend.activating.return_value = False + backend.connected = set() + return backend + + @pytest.mark.parametrize('change', [{'enabled': 1}, {'ssid': 'bad\nssid'}, {'password': 'short'}, {'password': 'has spaces in it'}, {'extra': True}, {'password': 'é' * 12}]) def test_strict_settings(change): @@ -79,7 +91,7 @@ def test_unregistered_name_is_not_invented(dongle): @pytest.mark.parametrize('status,expected', [('wpa_state=COMPLETED\nfreq=5745', ('a', 149)), ('wpa_state=COMPLETED\nfreq=2412', ('g', 1)), ('wpa_state=DISCONNECTED\nfreq=5745', ('g', 6)), ('wpa_state=INACTIVE', ('g', 6)), ('wpa_state=SCANNING', ('g', 6)), - ('wpa_state=ASSOCIATING', None), ('wpa_state=4WAY_HANDSHAKE\nfreq=5745', None), + ('wpa_state=ASSOCIATING', HOLD), ('wpa_state=4WAY_HANDSHAKE\nfreq=5745', HOLD), ('wpa_state=INTERFACE_DISABLED', None), ('FAIL', None), ('wpa_state=COMPLETED\nfreq=6000', None)]) def test_channel(status, expected): @@ -87,20 +99,157 @@ def test_channel(status, expected): def test_automatic_standalone_connected_and_back(): - now = [100] - backend = Mock() - backend.alive.return_value = backend.ready.return_value = True + now = [100.] + backend = backend_mock() controller = HotspotController(backend, clock=lambda: now[0]) for status, expected in [('DISCONNECTED', ('g', 6)), ('COMPLETED\nfreq=5745', ('a', 149)), ('DISCONNECTED', ('g', 6))]: backend.channel.return_value = radio_channel('wpa_state=' + status) assert controller.tick(CONFIG)['state'] == 'starting' backend.start.assert_called_with(CONFIG, expected) assert controller.tick(CONFIG)['active'] - now[0] += 20 + now[0] += STANDALONE_SETTLE_S + 1 assert backend.start.call_count == 3 assert controller.tick({**CONFIG, 'enabled': False})['state'] == 'disabled' +@pytest.mark.parametrize('results,expected', [ + ([('a', 149)], ('a', 149)), ([('g', 6)], ('g', 6)), ([None], None), ([HOLD, ('a', 149)], HOLD), + ([('a', 149), HOLD], HOLD), ([('g', 1), ('a', 149)], ('g', 1)), ([('g', 6), ('a', 149)], ('a', 149)), + ([None, ('a', 149)], ('a', 149)), ([('g', 6), None], ('g', 6))]) +def test_choose_channel(results, expected): + assert choose_channel(results) == expected + + +@pytest.mark.parametrize('state,expected', [('30 (disconnected)', False), ('50 (connecting (configuring))', True), + ('60 (connecting (need authentication))', True), ('100 (connected)', False), ('', False), ('junk', False)]) +def test_nm_activating(state, expected): + assert nm_activating(state) == expected + + +def test_join_leaves_running_ap_alone(): + now = [100.] + backend = backend_mock(ap_channel=1) + controller = HotspotController(backend, clock=lambda: now[0]) + backend.channel.return_value = ('g', 1) + controller.tick(CONFIG) + assert controller.tick(CONFIG)['active'] + backend.start.reset_mock() + backend.stop.reset_mock() + # Android Auto drops home Wi-Fi, scans, associates and joins the car on channel 149. + for channel in (('g', 6), HOLD, ('g', 6), HOLD): + backend.channel.return_value = channel + now[0] += 2 + assert controller.tick(CONFIG)['active'] + backend.stop.assert_not_called() + backend.start.assert_not_called() + backend.ap_status.return_value = {'ready': True, 'channel': 149} + backend.channel.return_value = ('a', 149) + assert controller.tick(CONFIG)['channel'] == 149 + backend.stop.assert_not_called() + backend.start.assert_not_called() + # Only a station gone for good moves the AP to its standalone channel. + backend.channel.return_value = ('g', 6) + now[0] += STANDALONE_SETTLE_S - 1 + assert controller.tick(CONFIG)['active'] + backend.start.assert_not_called() + now[0] += 2 + assert controller.tick(CONFIG)['state'] == 'starting' + backend.start.assert_called_once_with(CONFIG, ('g', 6)) + + +def test_hold_does_not_start_ap(): + backend = backend_mock() + backend.channel.return_value = HOLD + controller = HotspotController(backend, clock=lambda: 100) + assert controller.tick(CONFIG)['state'] == 'waiting' + backend.start.assert_not_called() + backend.stop.assert_not_called() + + +def test_backend_channel_reports_idle_stations_and_asks_networkmanager_only_for_them(tmp_path): + def command(args, **kwargs): + if args[0] == 'nmcli': + return Mock(returncode=0, stdout='50 (connecting (configuring))\n') + return Mock(returncode=0, stdout='wpa_state=DISCONNECTED\n') + run = Mock(side_effect=command) + backend = HotspotBackend(tmp_path, run=run, interfaces=Mock()) + assert backend.channel() == ('g', 6) and backend.idle == ['wlan0'] + assert all(call.args[0][0] != 'nmcli' for call in run.call_args_list) + assert backend.activating() + run.side_effect = lambda args, **kwargs: Mock(returncode=0, stdout='wpa_state=COMPLETED\nfreq=5745') + assert backend.channel() == ('a', 149) and backend.connected == {149} + assert not backend.activating() + assert all(call.args[0][-1] in ('status', 'wlan0') for call in run.call_args_list) + + +def test_backend_skips_car_station_without_status(tmp_path, monkeypatch): + monkeypatch.setattr(Path, 'exists', lambda self: True) + def command(args, **kwargs): + if args[2] == 'aa0': + assert kwargs['check'] is False + return Mock(returncode=255, stdout='Failed to connect to non-global ctrl_ifname: aa0') + return Mock(returncode=0, stdout='wpa_state=COMPLETED\nfreq=2412') + backend = HotspotBackend(tmp_path, run=Mock(side_effect=command), interfaces=Mock()) + assert backend.channel() == ('g', 1) + + +def test_networkmanager_join_holds_the_running_ap(): + now = [100.] + backend = backend_mock(ap_channel=1) + controller = HotspotController(backend, clock=lambda: now[0]) + backend.channel.return_value = ('g', 1) + controller.tick(CONFIG) + backend.start.reset_mock() + backend.channel.return_value = ('g', 6) + now[0] += STANDALONE_SETTLE_S + 1 + backend.activating.return_value = True + assert controller.tick(CONFIG)['active'] + backend.start.assert_not_called() + backend.activating.reset_mock() + backend.channel.return_value = ('g', 1) + backend.activating.return_value = False + controller.tick(CONFIG) + backend.activating.assert_not_called() # nothing to change, so nothing to ask + + +def test_ap_moved_by_the_driver_to_another_station_stays_there(): + backend = backend_mock(ap_channel=36) + controller = HotspotController(backend, clock=lambda: 100) + backend.channel.return_value = ('a', 36) + controller.tick(CONFIG) + backend.start.reset_mock() + backend.stop.reset_mock() + backend.connected = {36, 149} + backend.ap_status.return_value = {'ready': True, 'channel': 149} + for _ in range(3): + assert controller.tick(CONFIG) == {'active': True, 'state': 'active', 'reason': '', 'channel': 149} + backend.start.assert_not_called() + backend.stop.assert_not_called() + + +def test_dfs_channel_that_will_not_start_falls_back_to_standalone(): + now = [100.] + backend = backend_mock(ready=False) + controller = HotspotController(backend, clock=lambda: now[0]) + backend.channel.return_value = ('a', 100) + assert controller.tick(CONFIG)['state'] == 'starting' + now[0] += 16 + assert controller.tick(CONFIG)['state'] == 'error' + now[0] += 16 + backend.ap_status.return_value = {'ready': True, 'channel': 6} + assert controller.tick(CONFIG)['state'] == 'starting' + backend.start.assert_called_with(CONFIG, ('g', 6)) + + +def test_backend_ap_status(tmp_path): + run = Mock(return_value=Mock(returncode=0, stdout='state=ENABLED\nchannel=149\n')) + backend = HotspotBackend(tmp_path, run=run, interfaces=Mock()) + assert backend.ap_status() == {'ready': True, 'channel': 149} + assert run.call_count == 1 + run.return_value = Mock(returncode=255, stdout='') + assert backend.ap_status() == {'ready': False, 'channel': None} + + def test_routes_and_config(): assert not overlapping_routes([{'dst': 'default'}, {'dst': '192.168.180.0/24'}, {'dst': '172.31.254.0/24', 'dev': 'galaxy0'}]) assert overlapping_routes([{'dst': '172.31.0.0/16', 'dev': 'wlan0'}]) @@ -113,19 +262,18 @@ def test_routes_and_config(): def test_controller_lifecycle_and_channel_recovery(): - backend = Mock() + backend = backend_mock() backend.channel.return_value = ('a', 149) - backend.alive.return_value = backend.ready.return_value = True - now = [100] + now = [100.] controller = HotspotController(backend, clock=lambda: now[0]) assert controller.tick(CONFIG)['state'] == 'starting' assert controller.tick(CONFIG)['active'] backend.start.assert_called_once_with(CONFIG, ('a', 149)) - backend.channel.return_value = ('g', 6) + backend.channel.return_value = ('a', 36) assert controller.tick(CONFIG)['state'] == 'error' # rate limit restarts now[0] += 16 assert controller.tick(CONFIG)['state'] == 'starting' - backend.start.assert_called_with(CONFIG, ('g', 6)) + backend.start.assert_called_with(CONFIG, ('a', 36)) backend.channel.return_value = None assert controller.tick(CONFIG)['state'] == 'waiting' assert controller.applied is None @@ -134,10 +282,8 @@ def test_controller_lifecycle_and_channel_recovery(): def test_controller_readiness_and_failed_child(): - backend = Mock() + backend = backend_mock(ready=False) backend.channel.return_value = ('a', 149) - backend.alive.return_value = True - backend.ready.return_value = False now = [0] controller = HotspotController(backend, clock=lambda: now[0]) assert controller.tick(CONFIG)['state'] == 'starting' @@ -193,3 +339,16 @@ def test_netlink_encoding_and_refusal(): wireless.query.assert_not_called() wireless.delete('galaxy0') wireless.query.assert_called_once_with(22, 8, attribute(3, b'\x07\0\0\0'), ack=True) + + +def test_netlink_new_interface_payloads(): + wireless = WirelessInterfaces.__new__(WirelessInterfaces) + wireless.interfaces = Mock(return_value={'wlan0': {'type': 2, 'phy': 0, 'index': 1}}) + wireless.query = Mock() + wireless.family = 22 + wireless.create('galaxy0') + ap = attribute(1, struct.pack('I', 0)) + attribute(4, b'galaxy0\0') + attribute(5, struct.pack('I', 3)) + wireless.query.assert_called_with(22, 7, ap, ack=True) + wireless.create('aa0', iftype=2) + station = attribute(1, struct.pack('I', 0)) + attribute(4, b'aa0\0') + attribute(5, struct.pack('I', 2)) + wireless.query.assert_called_with(22, 7, station, ack=True) diff --git a/openpilot/starpilot/galaxy/web/js/hotspot.js b/openpilot/starpilot/galaxy/web/js/hotspot.js index cde50c6b0a..a453c82e6e 100644 --- a/openpilot/starpilot/galaxy/web/js/hotspot.js +++ b/openpilot/starpilot/galaxy/web/js/hotspot.js @@ -3,6 +3,8 @@ import { GxNotice } from "./notice.js" import { GxState } from "./state.js" import { GalaxySettingRow, switchRow } from "./galaxy-setting-row.js" +const validPassword = password => typeof password === 'string' && (password === '' || /^[\x21-\x7e]{12,63}$/.test(password)) + export function validHotspot(value) { return value?.version === 1 && /^[a-f0-9]{64}$/.test(value.revision) && typeof value.editable === 'boolean' && typeof value.active === 'boolean' && @@ -10,15 +12,18 @@ export function validHotspot(value) { typeof value.reason === 'string' && value.reason.length <= 256 && value.url === 'http://172.31.254.1:8082/' && typeof value.config?.enabled === 'boolean' && /^TheGalaxy-[a-f0-9]{4}$/.test(value.config.ssid) && - typeof value.config.password === 'string' && (value.config.password === '' || /^[\x21-\x7e]{12,63}$/.test(value.config.password)) + validPassword(value.config.password) } export const GalaxyHotspot = { components: { GxNotice, GxState, GalaxySettingRow }, props: { mode: String, unauthorized: Function }, - data: () => ({ snapshot: null, draft: null, revision: '', busy: false, error: '', notice: '', + data: () => ({ snapshot: null, draft: null, revision: '', busy: false, error: '', saveError: '', notice: '', showPassword: false, timer: null, controller: null, generation: 0, active: false }), - computed: { dirty() { return JSON.stringify(this.draft) !== JSON.stringify(this.snapshot?.config) } }, + computed: { + dirty() { return JSON.stringify(this.draft) !== JSON.stringify(this.snapshot?.config) }, + passwordValid() { return validPassword(this.draft?.password) }, + }, mounted() { this.start() }, beforeUnmount() { this.stop() }, watch: { mode() { this.stop(); this.start() } }, @@ -27,7 +32,7 @@ export const GalaxyHotspot = { start() { if (this.mode === 'local') { this.active = true; this.refresh() } }, stop() { this.active = false; this.generation++; clearTimeout(this.timer); this.controller?.abort() - this.snapshot = this.draft = null; this.revision = ''; this.showPassword = false; this.busy = false + this.snapshot = this.draft = null; this.revision = ''; this.showPassword = false; this.busy = false; this.saveError = '' }, adopt(value, reset = false) { if (!validHotspot(value)) throw new Error('Invalid hotspot status') @@ -53,10 +58,10 @@ export const GalaxyHotspot = { } }, async save() { - if (!this.active || this.busy || !this.snapshot?.editable) return + if (!this.active || this.busy || !this.snapshot?.editable || !this.passwordValid) return clearTimeout(this.timer); this.controller?.abort() const generation = ++this.generation - this.controller = new AbortController(); this.busy = true; this.error = ''; this.notice = '' + this.controller = new AbortController(); this.busy = true; this.saveError = ''; this.notice = '' try { const value = await requestJson('./api/galaxy/hotspot', { request: { signal: this.controller.signal, method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -68,7 +73,7 @@ export const GalaxyHotspot = { } catch (error) { if (!this.active || generation !== this.generation) return if (error.status === 401) { this.stop(); this.unauthorized(); return } - this.error = `${error.message} If Wi-Fi disconnected, reconnect and reload to check whether settings saved.` + this.saveError = `${error.message} If Wi-Fi disconnected, reconnect and reload to check whether settings saved.` } finally { if (this.active && generation === this.generation) { this.busy = false; this.timer = setTimeout(() => this.refresh(), 1000) } } @@ -87,7 +92,8 @@ export const GalaxyHotspot = {

Fixed to TheGalaxy- plus the last four characters of your comma dongle ID. Once saved, the switch and password survive restarts.

-
+

Use a 12–63 character password without spaces, or leave it blank to generate one.

+
Park before changing hotspot settings.

Join the network, stay connected if warned of no Internet, then open and bookmark {{ snapshot.url }}.

@@ -99,6 +105,6 @@ export const GalaxyHotspot = {
  • Network or channel changes may interrupt access. Changing the password or disabling the hotspot disconnects phones.
  • The public galaxy.firestar.link address still needs Internet and its tunnel.
  • - {{ error }}{{ notice }} + {{ error }}{{ saveError }}{{ notice }} `, } diff --git a/openpilot/starpilot/gps/phone.py b/openpilot/starpilot/gps/phone.py new file mode 100644 index 0000000000..03715c56c2 --- /dev/null +++ b/openpilot/starpilot/gps/phone.py @@ -0,0 +1,99 @@ +import json +import math +import threading +import time + +FIELDS = {"latitude", "longitude", "altitude", "speed", "bearing", "horizontalAccuracy", "verticalAccuracy", + "speedAccuracy", "bearingAccuracy", "timestamp", "ageMs"} +MAX_AGE_MS = 2000 + + +def _number(payload, key, required=False): + value = payload.get(key) + if value is None and not required: + return math.nan + if type(value) not in (int, float) or not math.isfinite(value): + raise ValueError(f"Invalid {key}") + return float(value) + + +def _optional(payload, key, low, high): + # Phones report an unknown value as null or a negative number. + value = _number(payload, key) + return value if low <= value < high else math.nan + + +def _required(payload, key, low, high, *, strict_low=False): + value = _number(payload, key, True) + if (value <= low if strict_low else value < low) or value >= high: + raise ValueError(f"Invalid {key}") + return value + + +def phone_gps(payload, now_ns): + if not isinstance(payload, dict) or set(payload) - FIELDS: + raise ValueError("Unexpected location fields") + latitude, longitude = _number(payload, "latitude", True), _number(payload, "longitude", True) + accuracy, age_ms = _number(payload, "horizontalAccuracy", True), _number(payload, "ageMs", True) + if not (-90 <= latitude <= 90 and -180 <= longitude <= 180) or (latitude == 0 and longitude == 0): + raise ValueError("Invalid position") + if not 0 < accuracy <= 10_000: + raise ValueError("Invalid accuracy") + if not 0 <= age_ms <= MAX_AGE_MS: + raise ValueError("Location is too old") + timestamp = payload.get("timestamp", 0) + if type(timestamp) is not int or not 0 <= timestamp < 2 ** 53: + raise ValueError("Invalid timestamp") + return { + "sourceMonoTime": now_ns - int(age_ms * 1e6), + "latitude": latitude, + "longitude": longitude, + "altitude": _required(payload, "altitude", -1000, 10_000), + "speed": _required(payload, "speed", 0, 100), + "bearingDeg": _required(payload, "bearing", 0, 360), + "horizontalAccuracy": accuracy, + "verticalAccuracy": _optional(payload, "verticalAccuracy", 0, 10_000), + "bearingAccuracyDeg": _required(payload, "bearingAccuracy", 0, 180, strict_low=True), + "speedAccuracy": _required(payload, "speedAccuracy", 0, 100), + "unixTimestampMillis": timestamp, + "hasFix": True, + } + + +def handoff_path(): + import tempfile + from pathlib import Path + shm = Path("/dev/shm") + return (shm if shm.is_dir() else Path(tempfile.gettempdir())) / "starpilot_phone_gps.json" + + +class PhoneGpsPublisher: + """Hands the newest validated phone fix to navigationd, which publishes it inside starpilotNavigation.""" + + def __init__(self, path=None, mono_clock=time.monotonic_ns): + self._path, self._mono_clock = path, mono_clock + self._lock = threading.Lock() + + def publish(self, payload): + gps = phone_gps(payload, self._mono_clock()) + path = self._path or handoff_path() + temporary = path.with_name(path.name + ".tmp") + with self._lock: + temporary.write_text(json.dumps(gps)) + temporary.replace(path) + return {"ok": True} + + +def read_phone_gps(now_ns, path=None): + """The handed-off fix as a Gps-like object, or None when absent, malformed or older than the phone hold.""" + from types import SimpleNamespace + from openpilot.starpilot.gps.source import PHONE_MAX_AGE_NS, valid_fix + try: + with (path or handoff_path()).open("rb") as source: + gps = json.loads(source.read(1 << 16)) + stamp = gps["sourceMonoTime"] + if type(stamp) is not int: + return None + return valid_fix(SimpleNamespace(**gps), stamp, stamp, now_ns, PHONE_MAX_AGE_NS) + except (OSError, ValueError, KeyError, TypeError): + return None diff --git a/openpilot/starpilot/gps/source.py b/openpilot/starpilot/gps/source.py index 46710ce44d..0a3138451c 100644 --- a/openpilot/starpilot/gps/source.py +++ b/openpilot/starpilot/gps/source.py @@ -1,30 +1,87 @@ +import json import math +import time -GPS_SOURCES = {"gpsLocationExternal": "ublox", "gpsLocation": "qcomdiag", "starpilotCarState": "car"} +GPS_SOURCES = {"gpsLocationExternal": "ublox", "gpsLocation": "qcomdiag", "starpilotCarState": "car", "phoneGps": "phone"} +GPS_PRIORITY = {"gpsLocationExternal": 2, "gpsLocation": 2, "starpilotCarState": 1, "phoneGps": 0} +WRAPPED_SOURCES = ("starpilotCarState", "phoneGps") GPS_MAX_AGE_NS = 2_500_000_000 +PHONE_MAX_AGE_NS = 10_000_000_000 # phones in the background send sparsely; keep the last fix this long +SOURCE_SERVICES = {"phoneGps": "starpilotNavigation"} # rides inside the navigation message +GPS_SERVICES = tuple(dict.fromkeys(SOURCE_SERVICES.get(name, name) for name in GPS_SOURCES)) +# backup: phone only without comma or car GPS; comma: never the phone; phone: the phone whenever it has a fix. +GPS_MODES = ("backup", "comma", "phone") +SOURCE_NAMES = {"gpsLocationExternal": "comma", "gpsLocation": "comma", "starpilotCarState": "car", "phoneGps": "phone"} +_mode: list = [-math.inf, "backup"] + + +def gps_mode(now=None): + """The GPS source chosen in Galaxy navigation settings, reread at most once a second.""" + now = time.monotonic() if now is None else now + if now - _mode[0] >= 1.: + try: + from openpilot.starpilot.storage import starpilot_storage_root + with (starpilot_storage_root() / "navigation" / "settings.json").open("rb") as source: + value = json.loads(source.read(1 << 20)).get("gpsSource", "backup") + except (OSError, ValueError, AttributeError): + value = "backup" + _mode[:] = [now, value if value in GPS_MODES else "backup"] + return _mode[1] + + +def gps_priority(service, mode): + """Rank of a source under the chosen mode, or None when it must not be used.""" + if service == "phoneGps": + return None if mode == "comma" else 3 if mode == "phone" else 0 + return GPS_PRIORITY[service] + + +def max_age_ns(service): + return PHONE_MAX_AGE_NS if service == "phoneGps" else GPS_MAX_AGE_NS + + +def valid_fix(gps, stamp, envelope, now_ns, max_age): + if (not gps.hasFix or not 0 < stamp <= envelope <= now_ns <= stamp + max_age or + not all(math.isfinite(v) for v in (gps.latitude, gps.longitude, gps.horizontalAccuracy)) or + not (-90 <= gps.latitude <= 90 and -180 <= gps.longitude <= 180 and 0 < gps.horizontalAccuracy <= 25)): + return None + return stamp, gps def observation(sm, service, now_ns): try: - gps = sm[service].gps if service == "starpilotCarState" else sm[service] - envelope = int(sm.logMonoTime[service]) - stamp = int(gps.sourceMonoTime) if service == "starpilotCarState" else envelope - if (not sm.valid[service] or not gps.hasFix or - not 0 < stamp <= envelope <= now_ns <= stamp + GPS_MAX_AGE_NS or - not all(math.isfinite(v) for v in (gps.latitude, gps.longitude, gps.horizontalAccuracy)) or - not (-90 <= gps.latitude <= 90 and -180 <= gps.longitude <= 180 and 0 < gps.horizontalAccuracy <= 25)): + carrier = SOURCE_SERVICES.get(service, service) + gps = (sm[carrier].phoneGps if service == "phoneGps" else sm[carrier].gps if service in WRAPPED_SOURCES else sm[carrier]) + envelope = int(sm.logMonoTime[carrier]) + stamp = int(gps.sourceMonoTime) if service in WRAPPED_SOURCES else envelope + if not sm.valid[carrier] or valid_fix(gps, stamp, envelope, now_ns, max_age_ns(service)) is None: return None - if service != "starpilotCarState" and str(gps.source) != GPS_SOURCES[service]: + if service not in WRAPPED_SOURCES and str(gps.source) != GPS_SOURCES[service]: return None return stamp, gps except (AttributeError, KeyError, TypeError, ValueError, OverflowError, RuntimeError): return None -def select_location(sm, now_ns): +def select_source(sm, now_ns, mode=None, phone_fix=None): + """The chosen fix and where it came from: (comma|car|phone, (stamp, gps)), or None.""" + mode = mode or gps_mode() + phone = None if mode == "comma" else phone_fix or observation(sm, "phoneGps", now_ns) + if mode == "phone" and phone is not None: + return "phone", phone native = [fix for service in ("gpsLocationExternal", "gpsLocation") if (fix := observation(sm, service, now_ns)) is not None] - return max(native, key=lambda fix: fix[0]) if native else observation(sm, "starpilotCarState", now_ns) + if native: + return "comma", max(native, key=lambda fix: fix[0]) + if (car := observation(sm, "starpilotCarState", now_ns)) is not None: + return "car", car + return ("phone", phone) if phone is not None else None + + +def select_location(sm, now_ns, mode=None, phone_fix=None): + """phone_fix: the navigation process's own phone fix, which it has before it publishes it.""" + selected = select_source(sm, now_ns, mode, phone_fix) + return selected[1] if selected is not None else None def bearing(gps): diff --git a/openpilot/starpilot/gps/tests/test_phone_gps.py b/openpilot/starpilot/gps/tests/test_phone_gps.py new file mode 100644 index 0000000000..1b4670e921 --- /dev/null +++ b/openpilot/starpilot/gps/tests/test_phone_gps.py @@ -0,0 +1,237 @@ +import math +import tempfile +from pathlib import Path +from types import SimpleNamespace +from unittest.mock import patch + +import pytest + +from openpilot.cereal import log, messaging +from openpilot.starpilot.gps.phone import PhoneGpsPublisher, phone_gps, read_phone_gps +from openpilot.starpilot.gps import source +from openpilot.starpilot.gps.source import GPS_SERVICES, PHONE_MAX_AGE_NS, gps_mode, select_location, select_source +from openpilot.starpilot.navigation.runtime import publish_status +from openpilot.starpilot.navigation.status import NavigationStatusSource + +NOW = 101_000_000_000 +PATH = Path(tempfile.gettempdir()) / "phone_gps.json" +FIX = {"latitude": 40., "longitude": -110., "horizontalAccuracy": 5., "ageMs": 300, "altitude": 100., "speed": 20., "bearing": 90., + "bearingAccuracy": 10., "speedAccuracy": 1., "timestamp": 1_790_000_000_000} + + +class Messages: + def __init__(self): + self.data = {} + self.valid = dict.fromkeys(GPS_SERVICES, False) + self.logMonoTime = dict.fromkeys(GPS_SERVICES, 0) + self.alive = dict.fromkeys(GPS_SERVICES, True) + self.seen = dict.fromkeys(GPS_SERVICES, True) + self.recv_time = dict.fromkeys(GPS_SERVICES, 0.) + + def __getitem__(self, key): + return self.data[key] + + def update(self, _timeout): + pass + + def send(self, service, message): + with log.Event.from_bytes(message.to_bytes()) as event: + value = getattr(event, service).to_dict() + if service == "starpilotCarState": + value["gps"] = SimpleNamespace(**getattr(event, service).gps.to_dict()) + if service == "starpilotNavigation": + value["phoneGps"] = SimpleNamespace(**getattr(event, service).phoneGps.to_dict()) + self.data[service] = SimpleNamespace(**value) + self.valid[service] = event.valid + self.logMonoTime[service] = event.logMonoTime + self.recv_time[service] = event.logMonoTime / 1e9 + + +class Bus: + def __init__(self, sm, now): + self.sm, self.now = sm, now + + def send(self, service, message): + message.logMonoTime = self.now + self.sm.send(service, message) + + +def publish(sm, payload=FIX, now=NOW, tmp_path=None): + """Galaxy hands the fix over; navigationd publishes it inside starpilotNavigation.""" + path = (tmp_path or PATH.parent) / "phone_gps.json" + result = PhoneGpsPublisher(path=path, mono_clock=lambda: now).publish(dict(payload)) + publish_status(Bus(sm, now), {"status": "idle"}, read_phone_gps(now, path)) + return result + + +def test_phone_is_used_only_without_another_fix(): + sm = Messages() + assert publish(sm) == {"ok": True} + stamp, gps = select_location(sm, NOW) + assert stamp == NOW - 300_000_000 and gps.longitude == -110. and gps.bearingDeg == 90. + + car = messaging.new_message("starpilotCarState", valid=True, logMonoTime=NOW) + car.starpilotCarState.gps = {"sourceMonoTime": NOW - 1, "latitude": 41., "longitude": -111., "horizontalAccuracy": 5., "hasFix": True} + sm.send("starpilotCarState", car) + assert select_location(sm, NOW)[1].longitude == -111. + + native = messaging.new_message("gpsLocation", valid=True, logMonoTime=NOW - 10_000_000) + native.gpsLocation = {"source": "qcomdiag", "hasFix": True, "horizontalAccuracy": 5., "longitude": -90., "latitude": 30.} + sm.send("gpsLocation", native) + assert select_location(sm, NOW)[1].longitude == -90. + + +def test_phone_fix_is_held_through_sparse_updates_then_expires(): + sm = Messages() + publish(sm) + stamp = NOW - 300_000_000 + assert select_location(sm, NOW + 2_300_000_000) is not None + assert select_location(sm, stamp + PHONE_MAX_AGE_NS) is not None + assert select_location(sm, stamp + PHONE_MAX_AGE_NS + 1) is None + + +def test_navigation_leaves_phone_empty_without_a_fresh_fix(tmp_path): + sm = Messages() + publish(sm, tmp_path=tmp_path) + later = NOW + PHONE_MAX_AGE_NS + 1_000_000_000 + assert read_phone_gps(later, tmp_path / "phone_gps.json") is None + publish_status(Bus(sm, later), {"status": "idle"}, None) + assert select_location(sm, later) is None + + +def test_phone_handoff_ignores_missing_and_damaged_files(tmp_path): + assert read_phone_gps(NOW, tmp_path / "missing.json") is None + (tmp_path / "bad.json").write_text("{") + assert read_phone_gps(NOW, tmp_path / "bad.json") is None + + +def test_unknown_vertical_accuracy_is_not_used(): + gps = phone_gps({**FIX, "verticalAccuracy": -1}, NOW) + assert math.isnan(gps["verticalAccuracy"]) + + +@pytest.mark.parametrize("field", ("altitude", "speed", "bearing", "bearingAccuracy", "speedAccuracy")) +def test_partial_fix_is_rejected(field): + payload = dict(FIX) + payload.pop(field) + with pytest.raises(ValueError, match=field): + phone_gps(payload, NOW) + + +@pytest.mark.parametrize("change", [{"ageMs": 2500}, {"ageMs": -1}, {"latitude": 91.}, {"latitude": 0., "longitude": 0.}, + {"horizontalAccuracy": 0}, {"latitude": True}, {"extra": 1}, {"timestamp": 1.5}, + {"speed": -1}, {"altitude": None}, {"bearingAccuracy": 0}, {"speedAccuracy": -1}]) +def test_invalid_fixes_are_rejected(change): + with pytest.raises(ValueError): + phone_gps({**FIX, **change}, NOW) + + +def test_inaccurate_phone_fix_is_published_but_not_selected(): + sm = Messages() + publish(sm, {**FIX, "horizontalAccuracy": 60.}) + assert sm.valid["starpilotNavigation"] and select_location(sm, NOW) is None + + +def test_navigation_status_ranks_phone_below_native(): + sm = Messages() + with patch('openpilot.cereal.messaging.SubMaster', return_value=sm): + status = NavigationStatusSource(mono_clock=lambda: NOW - 1_000_000_000, boot_clock=lambda: NOW) + status.mono_clock = lambda: NOW + publish(sm) + assert (status.map_position() or {})['longitude'] == -110. + native = messaging.new_message("gpsLocation", valid=True, logMonoTime=NOW - 500_000_000) + native.gpsLocation = {"source": "qcomdiag", "hasFix": True, "horizontalAccuracy": 5., "longitude": -90., "latitude": 30.} + sm.send("gpsLocation", native) + assert (status.map_position() or {})['longitude'] == -90. + + +def native(sm): + message = messaging.new_message("gpsLocation", valid=True, logMonoTime=NOW - 10_000_000) + message.gpsLocation = {"source": "qcomdiag", "hasFix": True, "horizontalAccuracy": 5., "longitude": -90., "latitude": 30.} + sm.send("gpsLocation", message) + + +def test_gps_modes_choose_phone_first_or_never(): + sm = Messages() + publish(sm) + assert select_location(sm, NOW, "comma") is None + native(sm) + assert select_location(sm, NOW, "backup")[1].longitude == -90. + assert select_location(sm, NOW, "comma")[1].longitude == -90. + assert select_location(sm, NOW, "phone")[1].longitude == -110. + assert select_location(sm, NOW + 2_300_000_000, "phone")[1].longitude == -110. + + +def test_gps_mode_follows_navigation_settings(tmp_path, monkeypatch): + monkeypatch.setattr("openpilot.starpilot.storage.starpilot_storage_root", lambda: tmp_path) + monkeypatch.setattr(source, "_mode", [-math.inf, "backup"]) + assert gps_mode(10.) == "backup" + (tmp_path / "navigation").mkdir() + (tmp_path / "navigation" / "settings.json").write_text('{"gpsSource": "phone"}') + assert gps_mode(10.5) == "backup" + assert gps_mode(11.) == "phone" + (tmp_path / "navigation" / "settings.json").write_text('{"gpsSource": "tunnel"}') + assert gps_mode(12.) == "backup" + + +@pytest.mark.parametrize("mode,longitude,name", [("backup", -90., "comma"), ("phone", -110., "phone"), ("comma", -90., "comma")]) +def test_navigation_status_reports_the_source_it_follows(mode, longitude, name): + sm = Messages() + with patch('openpilot.cereal.messaging.SubMaster', return_value=sm): + status = NavigationStatusSource(mono_clock=lambda: NOW - 1_000_000_000, boot_clock=lambda: NOW) + status.mono_clock = lambda: NOW + publish(sm) + native(sm) + with patch('openpilot.starpilot.navigation.status.gps_mode', return_value=mode): + position = status.map_position() + assert position is not None and position['longitude'] == longitude and position['source'] == name + assert 0 < position['validForMs'] <= 2500 + + +def test_phone_map_lease_is_capped_without_shortening_source_timeout(): + sm = Messages() + with patch('openpilot.cereal.messaging.SubMaster', return_value=sm): + status = NavigationStatusSource(mono_clock=lambda: NOW - 1_000_000_000, boot_clock=lambda: NOW) + clock = [NOW] + status.mono_clock = lambda: clock[0] + status.boot_clock = lambda: clock[0] + 1_000_000_000 + publish(sm) + with patch('openpilot.starpilot.navigation.status.gps_mode', return_value='backup'): + position = status.map_position() + assert position is not None and position['validForMs'] == 2500 + clock[0] += 8_000_000_000 + position = status.map_position() + assert position is not None and position['validForMs'] == 1700 + clock[0] += 2_000_000_000 + assert status.map_position() is None + + +def test_car_gps_ranks_against_the_phone_in_every_mode(): + sm = Messages() + publish(sm) + car = messaging.new_message("starpilotCarState", valid=True, logMonoTime=NOW) + car.starpilotCarState.gps = {"sourceMonoTime": NOW - 1, "latitude": 41., "longitude": -111., "horizontalAccuracy": 5., "hasFix": True} + sm.send("starpilotCarState", car) + assert select_location(sm, NOW, "backup")[1].longitude == -111. + assert select_location(sm, NOW, "comma")[1].longitude == -111. + assert select_location(sm, NOW, "phone")[1].longitude == -110. + with patch('openpilot.cereal.messaging.SubMaster', return_value=sm): + status = NavigationStatusSource(mono_clock=lambda: NOW - 1_000_000_000, boot_clock=lambda: NOW) + status.mono_clock = lambda: NOW + for mode, name in (("backup", "car"), ("comma", "car"), ("phone", "phone")): + with patch('openpilot.starpilot.navigation.status.gps_mode', return_value=mode): + assert (status.map_position() or {})['source'] == name + + +def test_selected_source_is_named(): + sm = Messages() + assert select_source(sm, NOW) is None + publish(sm) + assert select_source(sm, NOW)[0] == "phone" + car = messaging.new_message("starpilotCarState", valid=True, logMonoTime=NOW) + car.starpilotCarState.gps = {"sourceMonoTime": NOW - 1, "latitude": 41., "longitude": -111., "horizontalAccuracy": 5., "hasFix": True} + sm.send("starpilotCarState", car) + assert select_source(sm, NOW)[0] == "car" + native(sm) + assert select_source(sm, NOW)[0] == "comma" + assert select_source(sm, NOW, "phone")[0] == "phone" diff --git a/openpilot/starpilot/maps/provider/manifest.json b/openpilot/starpilot/maps/provider/manifest.json index 18c2ab6124..590e7c2ce7 100644 --- a/openpilot/starpilot/maps/provider/manifest.json +++ b/openpilot/starpilot/maps/provider/manifest.json @@ -1 +1 @@ -{"binarySha256":"348945f48bb8d8285aeb52840b562c7194d6f62cf8dc9f4b7bf63f75a00c35b0","goVersion":"go1.25.1","schemaVersion":1,"sourceDigest":"043c74946c10c3a06a4bd6f1470e6510e429e44cc03a28bcf49f8afd6e3fc787","sourceRevision":"a441889d43c31fad17059ec09defd1f71eb0eb85","target":"linux-arm64-static","upstreamRevision":"7201c6b4b4ec1b0b9ea21daa8c05b80fdd7e01ee"} +{"binarySha256":"327883964b0cbde92dd6c6ae03670495dd97d57869c806bb64cfbcfb73d96552","goVersion":"go1.25.1","schemaVersion":1,"sourceDigest":"8a77333de0bb02a9b3acd151a662cacaa078dbea36c1de62da790cff8ab1549c","sourceRevision":"127ddb75b6eb2861ce6327e42e12da80b318dd91","target":"linux-arm64-static","upstreamRevision":"7201c6b4b4ec1b0b9ea21daa8c05b80fdd7e01ee"} diff --git a/openpilot/starpilot/maps/provider/mapd b/openpilot/starpilot/maps/provider/mapd index 3c7ced9cb1..1bdac855d6 100755 Binary files a/openpilot/starpilot/maps/provider/mapd and b/openpilot/starpilot/maps/provider/mapd differ diff --git a/openpilot/starpilot/maps/shadow_lifecycle.py b/openpilot/starpilot/maps/shadow_lifecycle.py index 64bde44bf0..eadc5a5ecb 100644 --- a/openpilot/starpilot/maps/shadow_lifecycle.py +++ b/openpilot/starpilot/maps/shadow_lifecycle.py @@ -244,11 +244,14 @@ def enabled(started: bool, params: Params, CP: car.CarParams) -> bool: # processors so the runtime and its GC workers stay off most cores. SHADOW_NICE = 10 SHADOW_GOMAXPROCS = '2' +# Soft heap cap about 2x the densest tile's live set; Go returns the rest to the OS. +SHADOW_GOMEMLIMIT = '64MiB' def shadow_launcher(pargs: list[str], cwd: str, name: str) -> None: """In the forked child before exec, so every Go thread inherits it and the manager is untouched.""" os.environ['GOMAXPROCS'] = SHADOW_GOMAXPROCS + os.environ['GOMEMLIMIT'] = SHADOW_GOMEMLIMIT try: os.nice(SHADOW_NICE) except OSError: diff --git a/openpilot/starpilot/maps/tests/test_shadow_lifecycle.py b/openpilot/starpilot/maps/tests/test_shadow_lifecycle.py index cbcb93cc77..71b661f94a 100644 --- a/openpilot/starpilot/maps/tests/test_shadow_lifecycle.py +++ b/openpilot/starpilot/maps/tests/test_shadow_lifecycle.py @@ -212,16 +212,19 @@ class TestShadowLifecycle(unittest.TestCase): parent_nice = os.nice(0) with tempfile.TemporaryDirectory() as directory: out = Path(directory) / 'policy' - script = f'import os; open({str(out)!r}, "w").write(f"{{os.nice(0)}} {{os.environ.get(\'GOMAXPROCS\')}}")' + env = "{os.environ.get('GOMAXPROCS')} {os.environ.get('GOMEMLIMIT')}" + script = f'import os; open({str(out)!r}, "w").write(f"{{os.nice(0)}} {env}")' child = Process(target=shadow.shadow_launcher, args=([sys.executable, '-c', script], directory, 'mapd_shadow')) child.start() child.join(10) self.assertEqual(child.exitcode, 0) - nice, procs = out.read_text().split() + nice, procs, limit = out.read_text().split() self.assertEqual(int(nice), min(parent_nice + shadow.SHADOW_NICE, 19)) self.assertEqual(procs, shadow.SHADOW_GOMAXPROCS) + self.assertEqual(limit, shadow.SHADOW_GOMEMLIMIT) self.assertEqual(os.nice(0), parent_nice) self.assertNotEqual(os.environ.get('GOMAXPROCS'), shadow.SHADOW_GOMAXPROCS) + self.assertNotEqual(os.environ.get('GOMEMLIMIT'), shadow.SHADOW_GOMEMLIMIT) def test_exited_child_backoff_and_pending_shutdown(self): now = [10.0] diff --git a/openpilot/starpilot/models/jetlink_status.py b/openpilot/starpilot/models/jetlink_status.py new file mode 100644 index 0000000000..b00b189954 --- /dev/null +++ b/openpilot/starpilot/models/jetlink_status.py @@ -0,0 +1,130 @@ +"""Read-only Jetlink status for the home icon and the Android Auto card, polled off the drawing thread.""" +from __future__ import annotations + +from dataclasses import dataclass +import json +import math +import os +import threading +import time + +STALE_NS = 2_500_000_000 +# The host's processing time for the last big-model frame (excludes USB); jetlink's runtime record does not carry it +LATENCY_RECORD = "/dev/shm/jetlink/starpilot_latency.json" +LATENCY_FRESH_S = 3. +RUNNING = {'ready': 'ready', 'joining': 'connecting', 'retrying': 'connecting'} + + +@dataclass(frozen=True) +class JetlinkStatus: + device: str = '' + state: str = 'off' # off, disconnected, connected, connecting, ready, active, unavailable + latency_ms: float | None = None + port: str | None = None # jetlink's port_state: 'connected' (host on the link), 'device' (plugged in), else None + + +def _write_latency(model, path) -> None: + timings = getattr(getattr(model, "client", None), "last_timings", None) # the big model's client while it drives + total_us = timings[2] if isinstance(timings, (tuple, list)) and len(timings) == 3 else 0 + record = {"at": time.monotonic(), "server_ms": total_us / 1000 if type(total_us) in (int, float) and total_us > 0 else None} + os.makedirs(os.path.dirname(path), exist_ok=True) + tmp = f"{path}.tmp" + with open(tmp, "w") as f: + json.dump(record, f) + os.replace(tmp, path) + + +def start_latency_writer(model, path=LATENCY_RECORD, period=1.): + """modeld, before it goes realtime, so the thread keeps normal priority and the frame loop does no file IO.""" + def run(): + while True: + try: + _write_latency(model, path) + except Exception: + pass + time.sleep(period) + thread = threading.Thread(target=run, name="jetlink-latency", daemon=True) + thread.start() + return thread + + +def read_latency(path=LATENCY_RECORD) -> float | None: + try: + with open(path) as f: + record = json.load(f) + ms, at = record.get("server_ms"), record.get("at") + fresh = type(at) in (int, float) and 0 <= time.monotonic() - at < LATENCY_FRESH_S + return float(ms) if fresh and type(ms) in (int, float) and math.isfinite(ms) and ms > 0 else None + except (OSError, ValueError, AttributeError): + return None + + +def read_status() -> JetlinkStatus: + from openpilot.starpilot.models.jetlink_adapter import hooks, link_on + if not link_on(): + return JetlinkStatus() # one file read: nothing of jetlink's loads + status = hooks().status() + if status is None: + return JetlinkStatus(state='unavailable') + if not status.enabled: + return JetlinkStatus() # a Chestnut is fitted + device = 'iPhone' if status.mode == 'ios' else 'Computer' + port = status.port_state if status.port_state in ('connected', 'device') else None + if not status.present: + return JetlinkStatus(device, 'disconnected', port=port) + if status.active: + return JetlinkStatus(device, 'active', read_latency(), port) + if status.reason: + return JetlinkStatus(device, 'unavailable', port=port) + return JetlinkStatus(device, RUNNING.get(status.running, 'connected'), port=port) + + +class JetlinkStatusFeed: + """Polls once a second only while enabled; snapshot() never does file IO.""" + def __init__(self, read=read_status, period=1.0): + self.read, self.period = read, period + self._lock = threading.Lock() + self._stop = threading.Event() + self._thread = None + self._enabled = False + self._status = JetlinkStatus() + self._read_at = 0 + + def set_enabled(self, enabled): + with self._lock: + self._enabled = enabled + if not enabled: + self._status = JetlinkStatus() + if enabled and self._thread is None: + self._thread = threading.Thread(target=self._run, name='jetlink-status', daemon=True) + self._thread.start() + + def poll(self): + with self._lock: + if not self._enabled: + return + try: + status = self.read() + except Exception: + status = JetlinkStatus(state='unavailable') + with self._lock: + if self._enabled: + self._status = status + self._read_at = time.monotonic_ns() + + def snapshot(self): + with self._lock: + status, read_at = self._status, self._read_at + if status.state != 'off' and time.monotonic_ns() - read_at > STALE_NS: + return JetlinkStatus(status.device, 'unavailable') + return status + + def _run(self): + while not self._stop.is_set(): + self.poll() + self._stop.wait(self.period) + + def close(self): + self._stop.set() + if self._thread is not None: + self._thread.join(timeout=2) diff --git a/openpilot/starpilot/models/tests/test_jetlink_status.py b/openpilot/starpilot/models/tests/test_jetlink_status.py new file mode 100644 index 0000000000..0df784c931 --- /dev/null +++ b/openpilot/starpilot/models/tests/test_jetlink_status.py @@ -0,0 +1,94 @@ +"""Jetlink's home icon and Android Auto card read one status, off the drawing thread, never keeping stale latency.""" +import json +import threading +import time +from types import SimpleNamespace as NS +from unittest.mock import patch + +import pytest + +from openpilot.starpilot.models import jetlink_adapter as adapter, jetlink_status +from openpilot.starpilot.models.jetlink_status import JetlinkStatus, JetlinkStatusFeed, read_status + + +def status(**kw): + base = {'enabled': True, 'mode': 'usb', 'present': True, 'port_state': 'connected', 'active': False, 'reason': None, 'running': None} + return NS(**{**base, **kw}) + + +def read(value, latency=24.6): + with patch.object(adapter, 'link_on', return_value=True), \ + patch.object(adapter, 'hooks', return_value=NS(status=lambda: value)), \ + patch.object(jetlink_status, 'read_latency', return_value=latency): + return read_status() + + +def test_off_reads_nothing_of_jetlink(): + with patch.object(adapter, 'link_on', return_value=False), patch.object(adapter, 'hooks') as hooks: + assert read_status() == JetlinkStatus() + hooks.assert_not_called() + + +@pytest.mark.parametrize('kw,expected', [ + ({'active': True, 'running': 'running'}, JetlinkStatus('Computer', 'active', 24.6, 'connected')), + ({'running': 'ready'}, JetlinkStatus('Computer', 'ready', port='connected')), + ({'running': 'joining'}, JetlinkStatus('Computer', 'connecting', port='connected')), + ({'running': 'retrying'}, JetlinkStatus('Computer', 'connecting', port='connected')), + ({'running': None}, JetlinkStatus('Computer', 'connected', port='connected')), + ({'reason': 'service stopped'}, JetlinkStatus('Computer', 'unavailable', port='connected')), + ({'present': False, 'port_state': 'device'}, JetlinkStatus('Computer', 'disconnected', port='device')), + ({'present': False, 'port_state': 'empty'}, JetlinkStatus('Computer', 'disconnected')), + ({'present': False, 'port_state': None}, JetlinkStatus('Computer', 'disconnected')), + ({'mode': 'ios', 'active': True}, JetlinkStatus('iPhone', 'active', 24.6, 'connected')), + ({'enabled': False}, JetlinkStatus()), +]) +def test_states(kw, expected): + assert read(status(**kw)) == expected + + +def test_no_usable_jetlink_is_unavailable(): + assert read(None) == JetlinkStatus(state='unavailable') + + +def test_latency_record_round_trip_and_staleness(tmp_path): + path = str(tmp_path / 'jetlink' / 'latency.json') + jetlink_status._write_latency(NS(client=NS(last_timings=(1, 2, 24600))), path) + assert jetlink_status.read_latency(path) == pytest.approx(24.6) + jetlink_status._write_latency(NS(client=None), path) # the small model drives + assert jetlink_status.read_latency(path) is None + with open(path, 'w') as f: + json.dump({'at': time.monotonic() - jetlink_status.LATENCY_FRESH_S - 1, 'server_ms': 24.6}, f) + assert jetlink_status.read_latency(path) is None + assert jetlink_status.read_latency(str(tmp_path / 'missing.json')) is None + + +def test_feed_polls_off_thread_expires_and_disables(): + arrived = threading.Event() + threads = [] + def fake(): + threads.append(threading.get_ident()) + arrived.set() + return JetlinkStatus('iPhone', 'active', 24.6, 'connected') + feed = JetlinkStatusFeed(read=fake, period=0.01) + try: + assert feed.snapshot() == JetlinkStatus() + feed.set_enabled(True) + assert arrived.wait(2) + assert threading.get_ident() not in threads + assert feed.snapshot().latency_ms == 24.6 + feed.set_enabled(False) + assert feed.snapshot() == JetlinkStatus() + finally: + feed.close() + + +def test_feed_stale_and_failed_reads_drop_latency_and_port(): + feed = JetlinkStatusFeed(read=lambda: JetlinkStatus('iPhone', 'active', 24.6, 'connected')) + feed._enabled = True + feed.poll() + assert feed.snapshot().port == 'connected' + feed._read_at = 0 + assert feed.snapshot() == JetlinkStatus('iPhone', 'unavailable') + feed.read = lambda: 1 / 0 + feed.poll() + assert feed.snapshot() == JetlinkStatus(state='unavailable') diff --git a/openpilot/starpilot/navigation/owner.py b/openpilot/starpilot/navigation/owner.py index 4b2775e665..ee3b446fa4 100644 --- a/openpilot/starpilot/navigation/owner.py +++ b/openpilot/starpilot/navigation/owner.py @@ -23,6 +23,7 @@ import requests from openpilot.starpilot.storage import starpilot_storage_root from openpilot.starpilot.navigation.position import LastPositionStore +from openpilot.starpilot.gps.source import GPS_MODES MAX_DOCUMENT = 256 * 1024 MAX_RESPONSE = 8 * 1024 * 1024 @@ -145,7 +146,7 @@ class NavigationOwner: try: info = os.stat(self.path) except FileNotFoundError: - return {'version': 1, 'revision': '0', 'enabled': False, 'token': '', 'destination': None, 'favorites': [], 'recents': [], + return {'version': 1, 'revision': '0', 'enabled': False, 'token': '', 'destination': None, 'favorites': [], 'recents': [], 'gpsSource': 'backup', **dict.fromkeys(ROUTE_AVOIDANCES, False)} key = (info.st_ino, info.st_mtime_ns, info.st_size) cached = getattr(self, '_read_cache', None) @@ -155,7 +156,7 @@ class NavigationOwner: with self.path.open('rb') as source: raw = source.read(MAX_DOCUMENT + 1) except FileNotFoundError: - return {'version': 1, 'revision': '0', 'enabled': False, 'token': '', 'destination': None, 'favorites': [], 'recents': [], + return {'version': 1, 'revision': '0', 'enabled': False, 'token': '', 'destination': None, 'favorites': [], 'recents': [], 'gpsSource': 'backup', **dict.fromkeys(ROUTE_AVOIDANCES, False)} try: value = json.loads(raw) @@ -175,6 +176,8 @@ class NavigationOwner: for setting in ROUTE_AVOIDANCES: if type(value.setdefault(setting, False)) is not bool: raise ValueError + if value.setdefault('gpsSource', 'backup') not in GPS_MODES: + raise ValueError except (ValueError, TypeError, KeyError): raise ValidationError('Saved navigation settings could not be read') from None self._read_cache = (key, copy.deepcopy(value)) @@ -330,6 +333,7 @@ class NavigationOwner: 'noDestination' if document['destination'] is None else 'waitingForLocation') result = {key: document[key] for key in ('enabled', 'destination', 'recents', 'revision')} result.update({key: document[key] for key in ROUTE_AVOIDANCES}) + result['gpsSource'] = document['gpsSource'] # Home and Work lead, then places in the order they were saved. result['favorites'] = sorted(document['favorites'], key=lambda row: FAVORITE_LABELS.index(row['label']) if 'label' in row else 2) from openpilot.starpilot.navigation.mapbox_budget import read_usage @@ -478,8 +482,10 @@ class NavigationOwner: self._tile_bytes -= len(tile) def configure(self, patch: dict, expected_revision: str, authorized) -> dict: - if not isinstance(patch, dict) or not patch or set(patch) - ({'enabled', 'token'} | ROUTE_AVOIDANCES.keys()): + if not isinstance(patch, dict) or not patch or set(patch) - ({'enabled', 'token', 'gpsSource'} | ROUTE_AVOIDANCES.keys()): raise ValidationError('Unknown navigation setting') + if 'gpsSource' in patch and patch['gpsSource'] not in GPS_MODES: + raise ValidationError('Choose a GPS source') if 'enabled' in patch and type(patch['enabled']) is not bool: raise ValidationError('Navigation enabled must be on or off') if any(type(patch[key]) is not bool for key in ROUTE_AVOIDANCES if key in patch): @@ -493,7 +499,7 @@ class NavigationOwner: if any(key in patch and patch[key] != value[key] for key in ROUTE_AVOIDANCES): value['routeChoice'] = 0 value.update(patch) - result = self._change(update, expected_revision, authorized, preserve_active=set(patch) <= ROUTE_AVOIDANCES.keys()) + result = self._change(update, expected_revision, authorized, preserve_active=set(patch) <= ROUTE_AVOIDANCES.keys() | {'gpsSource'}) if 'token' in patch: with self._tile_lock: self._tiles.clear() diff --git a/openpilot/starpilot/navigation/runtime.py b/openpilot/starpilot/navigation/runtime.py index 47c978e218..1e15088a7f 100644 --- a/openpilot/starpilot/navigation/runtime.py +++ b/openpilot/starpilot/navigation/runtime.py @@ -9,14 +9,15 @@ import uuid from openpilot.starpilot.navigation.owner import ConflictError, NavigationOwner, ValidationError, ROUTE_AVOIDANCES from openpilot.starpilot.navigation.route_engine import MapboxRouteEngine -from openpilot.starpilot.gps.source import GPS_MAX_AGE_NS, GPS_SOURCES, bearing, select_location +from openpilot.starpilot.gps.phone import read_phone_gps +from openpilot.starpilot.gps.source import GPS_MAX_AGE_NS, GPS_SERVICES, bearing, select_location ARRIVED_NS = 5_000_000_000 # stopped at the destination this long shows "You have arrived" END_ROUTE_NS = 15_000_000_000 # ...and this long ends navigation, like tapping End navigation -def location(sm, now_ns: int): - fix = select_location(sm, now_ns) +def location(sm, now_ns: int, phone_fix=None): + fix = select_location(sm, now_ns, phone_fix=phone_fix) if fix is None: return None stamp, gps = fix @@ -148,11 +149,19 @@ class RouteRuntime: self.ended_revision = revision -def publish_status(pm, value: dict) -> None: +def phone_gps_dict(phone_fix) -> dict | None: + if phone_fix is None: + return None + gps = dict(vars(phone_fix[1])) + gps["vNED"] = list(gps.get("vNED", ())) + return gps + + +def publish_status(pm, value: dict, phone_fix=None) -> None: from openpilot.cereal import messaging message = messaging.new_message('starpilotNavigation', valid=True) from openpilot.starpilot.navigation.wire import navigation_envelope - message.starpilotNavigation = navigation_envelope(value) + message.starpilotNavigation = {**navigation_envelope(value), **({'phoneGps': gps} if (gps := phone_gps_dict(phone_fix)) else {})} pm.send('starpilotNavigation', message) @@ -162,9 +171,12 @@ def main(): from openpilot.common.swaglog import cloudlog owner = NavigationOwner() runtime = RouteRuntime(owner) - sm = messaging.SubMaster(['deviceState', *GPS_SOURCES]) + sm = messaging.SubMaster(['deviceState', *(service for service in GPS_SERVICES if service != 'starpilotNavigation')]) pm = messaging.PubMaster(['starpilotNavigation']) - rate = Ratekeeper(1.) + # Forward new phone measurements promptly; held fixes still need only a 1 Hz heartbeat. + rate = Ratekeeper(5.) + next_update_ns = 0 + last_phone_stamp = 0 try: while True: sm.update(0) @@ -174,8 +186,13 @@ def main(): drive_id = (device.startedMonoTime if sm.valid['deviceState'] and device.started and 0 < device.startedMonoTime <= device_stamp <= now <= device_stamp + 2_000_000_000 else 0) try: - value = runtime.update(now, location(sm, now), drive_id) - publish_status(pm, value) + phone_fix = read_phone_gps(now) + phone_stamp = phone_fix[0] if phone_fix is not None else 0 + if now >= next_update_ns or phone_stamp != last_phone_stamp: + next_update_ns = now + 1_000_000_000 + last_phone_stamp = phone_stamp + value = runtime.update(now, location(sm, now, phone_fix), drive_id) + publish_status(pm, value, phone_fix) except (ValidationError, OSError, ValueError): cloudlog.warning('navigation settings or route unavailable') rate.keep_time() diff --git a/openpilot/starpilot/navigation/status.py b/openpilot/starpilot/navigation/status.py index 362ac6a641..3da47e1f56 100644 --- a/openpilot/starpilot/navigation/status.py +++ b/openpilot/starpilot/navigation/status.py @@ -4,7 +4,7 @@ from openpilot.starpilot.parked_evidence import RESUME_SKEW_NS from openpilot.starpilot.navigation.wire import navigation_state -from openpilot.starpilot.gps.source import GPS_MAX_AGE_NS as GPS_TTL_NS, GPS_SOURCES, bearing, observation +from openpilot.starpilot.gps.source import GPS_SERVICES, GPS_SOURCES, SOURCE_NAMES, SOURCE_SERVICES, bearing, gps_mode, gps_priority, max_age_ns, observation def boot_time_ns(): @@ -14,7 +14,7 @@ def boot_time_ns(): class NavigationStatusSource: def __init__(self, *, mono_clock=time.monotonic_ns, boot_clock=boot_time_ns): from openpilot.cereal import messaging - self.sm = messaging.SubMaster(['starpilotNavigation', *GPS_SOURCES, 'deviceState']) + self.sm = messaging.SubMaster(list(dict.fromkeys(['starpilotNavigation', *GPS_SERVICES, 'deviceState']))) self.mono_clock, self.boot_clock = mono_clock, boot_clock self.gps_after_mono_ns = mono_clock() self.gps_offset_ns = None @@ -72,23 +72,28 @@ class NavigationStatusSource: self.gps_offset_ns = offset return None candidates = [] + mode = gps_mode() for service in GPS_SOURCES: try: - fix = observation(self.sm, service, after) + priority = gps_priority(service, mode) + fix = None if priority is None else observation(self.sm, service, after) if fix is None: continue stamp, gps = fix - receipt = int(self.sm.recv_time[service] * 1e9) - if (self.sm.seen[service] and self.sm.alive[service] and self.gps_after_mono_ns < stamp and - 0 <= after - receipt <= GPS_TTL_NS): + carrier, ttl = SOURCE_SERVICES.get(service, service), max_age_ns(service) + receipt = int(self.sm.recv_time[carrier] * 1e9) + if (self.sm.seen[carrier] and self.sm.alive[carrier] and self.gps_after_mono_ns < stamp and + 0 <= after - receipt <= ttl): direction = bearing(gps) - candidates.append((service != "starpilotCarState", stamp, - {'longitude': float(gps.longitude), 'latitude': float(gps.latitude), + candidates.append((priority, stamp, + {'longitude': float(gps.longitude), 'latitude': float(gps.latitude), 'source': SOURCE_NAMES[service], **({'bearing': direction} if direction is not None else {}), - 'validForMs': min(stamp + GPS_TTL_NS - after, receipt + GPS_TTL_NS - after) / 1e6})) + # Galaxy leases map markers for at most 2.5 seconds, even when + # a background phone fix has a longer source timeout. + 'validForMs': min(2500., (stamp + ttl - after) / 1e6, (receipt + ttl - after) / 1e6)})) except (AttributeError, KeyError, TypeError, ValueError, OverflowError, RuntimeError): continue - return max(candidates, default=(False, 0, None), key=lambda row: row[:2])[2] + return max(candidates, default=(-1, 0, None), key=lambda row: row[:2])[2] def close(self): for socket in getattr(self.sm, 'sock', {}).values(): diff --git a/openpilot/starpilot/navigation/tests/test_route_preferences.py b/openpilot/starpilot/navigation/tests/test_route_preferences.py index 096c446718..21b2730f8a 100644 --- a/openpilot/starpilot/navigation/tests/test_route_preferences.py +++ b/openpilot/starpilot/navigation/tests/test_route_preferences.py @@ -21,6 +21,15 @@ def owner(tmp_path, monkeypatch): return NavigationOwner(tmp_path, runtime_source=lambda: None, transient_root=tmp_path / 'runtime') +def test_gps_source_defaults_saves_and_rejects_unknown(owner): + assert owner.snapshot()['gpsSource'] == 'backup' + saved = owner.configure({'gpsSource': 'phone'}, '0', True) + assert owner.snapshot()['gpsSource'] == 'phone' + assert json.loads(owner.path.read_text())['gpsSource'] == 'phone' + with pytest.raises(ValidationError): + owner.configure({'gpsSource': 'tunnel'}, saved['revision'], True) + + def test_preferences_default_and_survive_restart(owner): assert all(owner.snapshot()[key] is False for key in ROUTE_AVOIDANCES) saved = owner.configure({'enabled': True, 'token': 'pk.test', 'avoidTolls': True}, '0', True) diff --git a/openpilot/starpilot/navigation/tests/test_route_runtime.py b/openpilot/starpilot/navigation/tests/test_route_runtime.py index db4edb34a7..2813b5f279 100644 --- a/openpilot/starpilot/navigation/tests/test_route_runtime.py +++ b/openpilot/starpilot/navigation/tests/test_route_runtime.py @@ -1,6 +1,8 @@ from concurrent.futures import Future +import sys import time from types import SimpleNamespace +from unittest.mock import Mock import pytest @@ -9,6 +11,65 @@ from openpilot.starpilot.navigation.route_engine import NavigationRoute, project from openpilot.starpilot.navigation.runtime import RouteRuntime, location, publish_status +@pytest.mark.parametrize('changes, expected', [ + ({0: 1}, [0, 5, 10]), # sparse/background measurements keep the normal heartbeat + ({index: index + 1 for index in range(11)}, list(range(11))), + ({0: 1, 2: 2, 3: 0}, [0, 2, 3, 8]), # replacement and expiry are forwarded immediately +]) +def test_navigation_forwards_new_phone_fixes_without_waiting_for_heartbeat(monkeypatch, changes, expected): + from openpilot.cereal import messaging + from openpilot.starpilot.navigation import runtime as module + + frame = [0] + stamp = [0] + phone = SimpleNamespace(speed=0.) + def now(): + return 100_000_000_000 + frame[0] * 200_000_000 + + def read_phone(_now): + stamp[0] = changes.get(frame[0], stamp[0]) + return (99_000_000_000 + stamp[0], phone) if stamp[0] else None + + class Finished(Exception): + pass + + class Rate: + def __init__(self, hz): + assert hz == 5. + + def keep_time(self): + frame[0] += 1 + if frame[0] > 10: + raise Finished + + owner, runtime = Mock(), Mock() + # Only device-state validity is relevant to this loop; source selection is tested separately. + class Master: + valid, logMonoTime = {'deviceState': False}, {'deviceState': 0} + def update(self, _timeout): + pass + def __getitem__(self, _service): + return SimpleNamespace(startedMonoTime=0) + + published = [] + monkeypatch.setitem(sys.modules, 'openpilot.common.realtime', SimpleNamespace(Ratekeeper=Rate)) + monkeypatch.setattr(module, 'NavigationOwner', lambda: owner) + monkeypatch.setattr(module, 'RouteRuntime', lambda _owner: runtime) + monkeypatch.setattr(module.time, 'monotonic_ns', now) + monkeypatch.setattr(module, 'read_phone_gps', read_phone) + monkeypatch.setattr(module, 'location', lambda _sm, _now, fix: fix) + monkeypatch.setattr(module, 'publish_status', lambda _pm, _value, fix: published.append((frame[0], fix))) + monkeypatch.setattr(messaging, 'SubMaster', lambda _services: Master()) + monkeypatch.setattr(messaging, 'PubMaster', lambda _services: None) + with pytest.raises(Finished): + module.main() + assert [index for index, _fix in published] == expected + assert runtime.update.call_count == len(expected) + if changes == {0: 1}: + assert {fix[0] for _index, fix in published} == {99_000_000_001}, 'held fixes keep their measurement time' + owner.position_store.flush.assert_called_once_with(force=True) + + @pytest.fixture def route(): return NavigationRoute({'distance': 1112., 'duration': 100., 'geometry': {'coordinates': [[0., 0.], [.01, 0.]]}, 'legs': [{'steps': [ diff --git a/openpilot/starpilot/navigation/tests/test_search_proximity.py b/openpilot/starpilot/navigation/tests/test_search_proximity.py index 74142ed028..83982e80b3 100644 --- a/openpilot/starpilot/navigation/tests/test_search_proximity.py +++ b/openpilot/starpilot/navigation/tests/test_search_proximity.py @@ -8,7 +8,7 @@ import pytest from openpilot.cereal import log, messaging from openpilot.starpilot.navigation.owner import NavigationOwner, ValidationError -from openpilot.starpilot.navigation.status import GPS_SOURCES, NavigationStatusSource +from openpilot.starpilot.navigation.status import GPS_SERVICES, GPS_SOURCES, NavigationStatusSource POI = {'mapbox_id': 'poi/id', 'name': 'Coffee', 'feature_type': 'poi'} @@ -24,7 +24,7 @@ class Clock: class Messages: def __init__(self, clock): self.clock = clock - names = ['starpilotNavigation', *GPS_SOURCES, 'deviceState'] + names = ['starpilotNavigation', *GPS_SERVICES, 'deviceState'] self.seen = dict.fromkeys(names, True) self.alive = dict.fromkeys(names, True) self.valid = dict.fromkeys(names, True) @@ -243,7 +243,7 @@ def test_cancel_during_optional_context_never_sends_provider_or_fallback(tmp_pat def test_map_position_lease_uses_oldest_envelope_or_receipt_and_expires(source): reader, sm, clock = source sm.valid['gpsLocation'] = False - assert reader.map_position() == {'longitude': -87.63, 'latitude': 41.88, 'validForMs': 2480.} + assert reader.map_position() == {'longitude': -87.63, 'latitude': 41.88, 'source': 'comma', 'validForMs': 2480.} sm.recv_time['gpsLocationExternal'] = (clock.mono - 500_000_000) / 1e9 assert reader.map_position()['validForMs'] == 2000. clock.mono += 2_000_000_001 diff --git a/openpilot/starpilot/software/fast_update.py b/openpilot/starpilot/software/fast_update.py index 95b6f6503e..00bcfc3648 100644 --- a/openpilot/starpilot/software/fast_update.py +++ b/openpilot/starpilot/software/fast_update.py @@ -6,6 +6,8 @@ import time import selectors import signal +from openpilot.starpilot.galaxy.companion import phone_uplink_active + from openpilot.common.vendor_manifest import validate_revision from openpilot.common.prebuilt_manifest import revision_digest, valid_receipt @@ -47,6 +49,9 @@ def _stop_process(process): def run(command, cwd, progress=None, *, timeout=None): + downloading = 'fetch' in command or 'pull' in command or 'clone' in command + if downloading and phone_uplink_active(): + raise FastUpdateError('Software downloads are disabled on the phone uplink') environment = dict(os.environ, GIT_LFS_SKIP_SMUDGE='1', GIT_TERMINAL_PROMPT='0', GIT_ASKPASS='/bin/false', SSH_ASKPASS='/bin/false') if timeout is None: timeout = 120 if "fetch" in command or "reset" in command or "checkout" in command else 30 @@ -59,6 +64,8 @@ def run(command, cwd, progress=None, *, timeout=None): pending = b"" try: while selector.get_map(): + if downloading and phone_uplink_active(): + raise FastUpdateError('Phone uplink activated; software download stopped') if time.monotonic() >= deadline: raise subprocess.TimeoutExpired(command, timeout, output=bytes(output)) for key, _ in selector.select(min(0.1, max(0.0, deadline - time.monotonic()))): diff --git a/openpilot/starpilot/state_migration.py b/openpilot/starpilot/state_migration.py index 6ca3110118..ae5b68c8a7 100644 --- a/openpilot/starpilot/state_migration.py +++ b/openpilot/starpilot/state_migration.py @@ -24,7 +24,7 @@ MAX_SNAPSHOT_BYTES = 256 * 1024 * 1024 MAX_KEYS = 4096 OPERATIONAL_KEYS = frozenset({ 'DongleId', 'HardwareSerial', 'GithubSshKeys', 'GithubUsername', 'SshEnabled', - 'GsmApn', 'GsmMetered', 'GsmRoaming', 'NetworkMetered', 'BluetoothEnabled', + 'CellularDisabled', 'GsmApn', 'GsmMetered', 'GsmRoaming', 'NetworkMetered', 'BluetoothEnabled', 'ConnectProvider', 'PairingProvider', 'PairingEmail', 'PrimeType', 'AssistNowToken', 'SecOCKey', }) diff --git a/openpilot/starpilot/system/pipe_worker.py b/openpilot/starpilot/system/pipe_worker.py new file mode 100644 index 0000000000..59bac181df --- /dev/null +++ b/openpilot/starpilot/system/pipe_worker.py @@ -0,0 +1,49 @@ +"""Shared plumbing for the root workers that unprivileged daemons lease over a pipe. + +The daemon starts the worker with ``spawn``. EOF on the worker's stdin, a missed heartbeat or SIGTERM ends the +lease, and the worker then removes only what it created (interfaces it marked with its own alias). +""" +from __future__ import annotations + +import fcntl +import os +import signal +import subprocess +import sys +import threading +from pathlib import Path + + +def spawn(unit: str, module: str, popen=subprocess.Popen): + from openpilot.common.basedir import BASEDIR + return popen(['sudo', '-n', 'systemd-run', '--quiet', '--pipe', '--wait', '--collect', f'--unit={unit}', + '--property=TimeoutStopSec=8', '--property=KillMode=control-group', '--working-directory=' + str(BASEDIR), + sys.executable, '-u', '-m', module], cwd=BASEDIR, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, close_fds=True) + + +def owned(interface: str, alias: str) -> bool: + try: + return Path(f'/sys/class/net/{interface}/ifalias').read_text().strip() == alias + except FileNotFoundError: + return False + + +def claim(runtime: Path, name: str) -> int: + """Root check, a private runtime directory and its lock; returns the lock's file descriptor.""" + if os.geteuid() != 0: + raise RuntimeError(f'{name} requires network administration privileges') + os.umask(0o077) + runtime.mkdir(mode=0o700, exist_ok=True) + if runtime.is_symlink() or runtime.stat().st_uid != 0: + raise RuntimeError(f'Unsafe {name} runtime directory') + fd = os.open(runtime / 'lock', os.O_CREAT | os.O_RDWR | os.O_NOFOLLOW, 0o600) + fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + return fd + + +def stop_event() -> threading.Event: + stop = threading.Event() + signal.signal(signal.SIGTERM, lambda *_: stop.set()) + signal.signal(signal.SIGINT, lambda *_: stop.set()) + return stop diff --git a/openpilot/starpilot/tests/test_external_preferences_reset.py b/openpilot/starpilot/tests/test_external_preferences_reset.py index c1d6553a69..60ffe7895b 100644 --- a/openpilot/starpilot/tests/test_external_preferences_reset.py +++ b/openpilot/starpilot/tests/test_external_preferences_reset.py @@ -32,7 +32,9 @@ selected.extend(node for node in owner_ast.body if isinstance(node, ast.Assign) owner_class = next(node for node in owner_ast.body if isinstance(node, ast.ClassDef) and node.name == 'NavigationOwner') selected.append(next(node for node in owner_class.body if isinstance(node, ast.FunctionDef) and node.name == 'read')) namespace: dict = {'json': json, 'math': math, 'hashlib': hashlib, 'os': os, 'copy': copy, 'MAX_DOCUMENT': 256 * 1024, - 'MAX_FAVORITES': 100, 'MAX_RECENTS': 10, 'FAVORITE_LABELS': ('home', 'work')} + 'MAX_FAVORITES': 100, 'MAX_RECENTS': 10, 'FAVORITE_LABELS': ('home', 'work'), + 'GPS_MODES': next(ast.literal_eval(node.value) for node in ast.parse((ROOT / 'gps' / 'source.py').read_text()).body + if isinstance(node, ast.Assign) and any(getattr(t, 'id', '') == 'GPS_MODES' for t in node.targets))} exec(compile(ast.Module(body=selected, type_ignores=[]), str(ROOT / 'navigation' / 'owner.py'), 'exec'), namespace) NavigationOwner = type('NavigationOwner', (), {'read': namespace['read']}) with patch.dict(sys.modules, {'openpilot.starpilot.state_migration': migration}): diff --git a/openpilot/starpilot/ui/tests/test_ioniq6_alpha_request.py b/openpilot/starpilot/ui/tests/test_ioniq6_alpha_request.py index ecf822f169..928966641e 100644 --- a/openpilot/starpilot/ui/tests/test_ioniq6_alpha_request.py +++ b/openpilot/starpilot/ui/tests/test_ioniq6_alpha_request.py @@ -63,6 +63,7 @@ def test_request_survives_capability_loss_and_recovery(module, layout): panel._adb_toggle = Toggle() panel._ssh_toggle = Toggle() panel._ui_debug_toggle = Toggle() + panel._cellular_disabled_toggle = Toggle() else: panel._refresh_toggles = (('AlphaLongitudinalEnabled', panel._alpha_long_toggle),) with patch.object(module, 'ui_state', ui): @@ -122,6 +123,7 @@ def test_release_preserves_request_without_advertising_passive_authority(module, panel._adb_toggle = Toggle() panel._ssh_toggle = Toggle() panel._ui_debug_toggle = Toggle() + panel._cellular_disabled_toggle = Toggle() else: panel._refresh_toggles = (('AlphaLongitudinalEnabled', panel._alpha_long_toggle),) with patch.object(module, 'ui_state', ui): diff --git a/openpilot/starpilot/ui/tests/test_runtime_panel_actions.py b/openpilot/starpilot/ui/tests/test_runtime_panel_actions.py index b835d4ceb4..a5b9894a1c 100644 --- a/openpilot/starpilot/ui/tests/test_runtime_panel_actions.py +++ b/openpilot/starpilot/ui/tests/test_runtime_panel_actions.py @@ -957,6 +957,6 @@ def test_compact_developer_fps_is_live_onroad_but_physical_controls_keep_native_ assert page._joystick_toggle.set_enabled.call_args.args[0]() is False assert page._alpha_long_toggle.set_enabled.call_args.args[0]() is False page._debug_mode_toggle.set_enabled.assert_not_called() - debug.call_args.kwargs['toggle_callback'](True) + next(c for c in debug.call_args_list if c.args[0] == "ui debug mode").kwargs['toggle_callback'](True) touches.assert_called_once_with(True) fps.assert_called_once_with(True) diff --git a/openpilot/system/athena/athenad.py b/openpilot/system/athena/athenad.py index 71aa181563..36c55d54d8 100755 --- a/openpilot/system/athena/athenad.py +++ b/openpilot/system/athena/athenad.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 from __future__ import annotations +from openpilot.starpilot.galaxy.companion import phone_uplink_active + import base64 import hashlib import itertools @@ -259,6 +261,8 @@ def retry_upload(tid: int, end_event: threading.Event, increase_count: bool = Tr def cb(sm, item, tid, end_event: threading.Event, sz: int, cur: int) -> None: # Abort transfer if connection changed to metered after starting upload # or if athenad is shutting down to re-connect the websocket + if phone_uplink_active(): + raise AbortTransferException if not item.allow_cellular: if (time.monotonic() - sm.recv_time['deviceState']) > DEVICE_STATE_UPDATE_INTERVAL: sm.update(0) @@ -295,7 +299,7 @@ def upload_handler(end_event: threading.Event) -> None: sm.update(0) metered = sm['deviceState'].networkMetered network_type = sm['deviceState'].networkType.raw - if metered and not item.allow_cellular and not Params().get_bool("AlwaysAllowUploads"): + if phone_uplink_active() or (metered and not item.allow_cellular and not Params().get_bool("AlwaysAllowUploads")): retry_upload(tid, end_event, False) continue diff --git a/openpilot/system/hardware/hardwared.py b/openpilot/system/hardware/hardwared.py index 1c43322641..f860b44591 100755 --- a/openpilot/system/hardware/hardwared.py +++ b/openpilot/system/hardware/hardwared.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +from openpilot.starpilot.galaxy.companion import phone_uplink_active + import fcntl import os import queue @@ -190,7 +192,8 @@ def hw_state_thread(end_event, hw_queue): if (count % int(10. / DT_HW)) == 0 or usb_changed: prev_usb_topology = usb_topology try: - network_type = HARDWARE.get_network_type() + phone_uplink = phone_uplink_active() + network_type = NetworkType.cell4G if phone_uplink else HARDWARE.get_network_type() modem_temps = HARDWARE.get_modem_temperatures() if len(modem_temps) == 0 and prev_hw_state is not None: modem_temps = prev_hw_state.modem_temps @@ -202,7 +205,7 @@ def hw_state_thread(end_event, hw_queue): network_info=HARDWARE.get_network_info(), network_strength=HARDWARE.get_network_strength(network_type), network_stats={'wwanTx': tx, 'wwanRx': rx}, - network_metered=HARDWARE.get_network_metered(network_type), + network_metered=phone_uplink or HARDWARE.get_network_metered(network_type), modem_temps=modem_temps, usb_state=get_usb_state(), ) diff --git a/openpilot/system/loggerd/uploader.py b/openpilot/system/loggerd/uploader.py index 736972c37d..1f967fbaad 100755 --- a/openpilot/system/loggerd/uploader.py +++ b/openpilot/system/loggerd/uploader.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +from openpilot.starpilot.galaxy.companion import phone_uplink_active + import json import os import random @@ -12,7 +14,7 @@ from collections.abc import Iterator from openpilot.cereal import log import openpilot.cereal.messaging as messaging from openpilot.common.api import Api -from openpilot.common.utils import get_upload_stream +from openpilot.common.utils import CallbackReader, get_upload_stream from openpilot.common.params import Params from openpilot.common.realtime import set_core_affinity from openpilot.common.hardware.hw import Paths @@ -179,6 +181,11 @@ class Uploader: return None def do_upload(self, key: str, fn: str): + def guard(*_): + if phone_uplink_active(): + raise requests.exceptions.ConnectionError("Phone uplink forbids log uploads") + + guard() url_resp = self.api.get("v1.4/" + self.dongle_id + "/upload_url/", timeout=10, path=key, access_token=self.api.get_token()) if url_resp.status_code == 412: return url_resp @@ -194,8 +201,8 @@ class Uploader: stream = None try: compress = key.endswith('.zst') and not fn.endswith('.zst') - stream, _ = get_upload_stream(fn, compress) - response = requests.put(url, data=stream, headers=headers, timeout=10) + stream, length = get_upload_stream(fn, compress) + response = requests.put(url, data=CallbackReader(stream, guard, length), headers=headers, timeout=10) return response finally: if stream: @@ -252,6 +259,8 @@ class Uploader: def step(self, network_type: int, metered: bool) -> bool | None: + if phone_uplink_active(): + return None d = self.next_file_to_upload(metered) if d is None: return None @@ -297,7 +306,7 @@ def main(exit_event: threading.Event | None = None) -> None: always_allow_uploads = params.get_bool("AlwaysAllowUploads") offroad = params.get_bool("IsOffroad") network_type = sm['deviceState'].networkType if not force_wifi else NetworkType.wifi - if network_type == NetworkType.none: + if phone_uplink_active() or network_type == NetworkType.none: if allow_sleep: time.sleep(60 if offroad else 5) continue diff --git a/openpilot/system/manager/manager.py b/openpilot/system/manager/manager.py index f9b5bc9411..6bf56129b1 100755 --- a/openpilot/system/manager/manager.py +++ b/openpilot/system/manager/manager.py @@ -229,13 +229,6 @@ def main() -> None: # SystemExit on sigterm signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(1)) - analytics = None - try: - from openpilot.starpilot.analytics.runtime import start_optional_worker - analytics = start_optional_worker() - except Exception: - cloudlog.warning("Usage statistics worker unavailable") - try: manager_thread() except Exception: @@ -244,11 +237,6 @@ def main() -> None: sentry.capture_exception() sentry.flush() finally: - if analytics is not None: - try: - analytics.close() - except Exception: - cloudlog.warning("Usage statistics shutdown failed") try: from openpilot.starpilot.system.jetlink.lifecycle import shutdown as shutdown_jetlink shutdown_jetlink(Params()) diff --git a/openpilot/system/manager/process_config.py b/openpilot/system/manager/process_config.py index 09695cd71c..634a06db97 100644 --- a/openpilot/system/manager/process_config.py +++ b/openpilot/system/manager/process_config.py @@ -143,6 +143,8 @@ procs = [ enabled=platform.system() == "Linux", restart_on_exit=True), PythonProcess("galaxy_hotspot", "openpilot.starpilot.galaxy.hotspot_daemon", galaxy_local, enabled=COMMA_HARDWARE and not os.environ.get('OPENPILOT_PREFIX'), restart_on_exit=True), + PythonProcess("companion_uplink", "openpilot.starpilot.galaxy.companion_uplink_daemon", galaxy_local, + enabled=COMMA_HARDWARE and not os.environ.get('OPENPILOT_PREFIX'), restart_on_exit=True), JetlinkProcess("jetlinkd", "openpilot.starpilot.models.jetlink_adapter", jetlink_enabled, enabled=COMMA_HARDWARE, restart_on_exit=True), PythonProcess("android_autod", "openpilot.starpilot.system.android_auto.daemon", android_auto_enabled, enabled=COMMA_HARDWARE, @@ -174,6 +176,7 @@ procs = [ PythonProcess("radard", "openpilot.selfdrive.controls.radard", only_onroad), PythonProcess("hardwared", "openpilot.system.hardware.hardwared", always_run), PythonProcess("modem", "openpilot.common.hardware.comma.modem", always_run, enabled=COMMA_HARDWARE), + PythonProcess("usage_stats", "openpilot.starpilot.analytics.runtime", always_run, enabled=COMMA_HARDWARE), PythonProcess("tombstoned", "openpilot.system.tombstoned", always_run, enabled=not PC), PythonProcess("updated", "openpilot.system.updated.updated", only_offroad, enabled=not PC), PythonProcess("uploader", "openpilot.system.loggerd.uploader", always_run), diff --git a/openpilot/system/updated/updated.py b/openpilot/system/updated/updated.py index 275a80aa17..73be579e50 100755 --- a/openpilot/system/updated/updated.py +++ b/openpilot/system/updated/updated.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +from openpilot.starpilot.galaxy.companion import phone_uplink_active + import os import re import datetime @@ -500,6 +502,8 @@ class Updater: init_overlay() self._branches_checked = False self.params.put("UpdaterState", "checking...", block=True) + if phone_uplink_active(): + raise FastUpdateError("Software downloads are disabled while using phone internet") if not self.fetch_update(): raise FastUpdateError("Target branch is no longer available") admitted() @@ -510,6 +514,8 @@ class Updater: return "reboot-requested" def fetch_update(self) -> bool: + if phone_uplink_active(): + return False if not self._branches_checked: self.check_for_update() if self.target_branch not in self.branches: @@ -647,7 +653,9 @@ def main() -> None: last_fetch = params.get("UpdaterLastFetchTime") timed_out = last_fetch is None or (datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_fetch > datetime.timedelta(days=3)) user_requested_fetch = requested == UserRequest.FETCH - if params.get_bool("NetworkMetered") and not timed_out and not user_requested_fetch: + if phone_uplink_active(): + cloudlog.info("skipping fetch, phone uplink forbids updates") + elif params.get_bool("NetworkMetered") and not timed_out and not user_requested_fetch: cloudlog.info("skipping fetch, connection metered") elif not download_permitted(params, manual=user_requested_fetch, check_only=requested == UserRequest.CHECK): cloudlog.info("skipping fetch, check-only request or automatic downloads disabled") diff --git a/pyproject.toml b/pyproject.toml index 3e27a156c3..1feeda4868 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -122,9 +122,9 @@ allow-direct-references = true [tool.codespell] quiet-level = 3 # if you've got a short variable name that's getting flagged, add it here -ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn,ws,uint,grey,deque,stdio,amin,BA,LITE,atEnd,UIs,errorString,arange,FocusIn,od,tim,relA,hist,copyable,jupyter,thead,TGE,abl,lite,ser,assertIn,HomeState,cancelled,CAS,acknowledgement,writeable,noice,FoF,waitFor,centre,centres" +ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn,ws,uint,grey,deque,stdio,amin,BA,LITE,atEnd,UIs,errorString,arange,FocusIn,od,tim,relA,hist,copyable,jupyter,thead,TGE,abl,lite,ser,assertIn,HomeState,cancelled,CAS,acknowledgement,writeable,noice,FoF,waitFor,centre,centres,KeyPair,aPoint" builtin = "clear,rare,informal,code,names,en-GB_to_en-US" -skip = "openpilot/cereal/gen/cpp/*.capnp.c++, openpilot/cereal/gen/cpp/*.capnp.h, *.po, uv.lock, *.onnx, *.pem, */c_generated_code/*, docs/assets/*, openpilot/tools/plotjuggler/layouts/*, openpilot/selfdrive/assets/offroad/mici_fcc.html, openpilot/starpilot/galaxy/web/vendor/vue/vue.esm-browser.js, openpilot/starpilot/ui/assets/fonts/notices/Unifont-COPYING.txt" +skip = "openpilot/cereal/gen/cpp/*.capnp.c++, openpilot/cereal/gen/cpp/*.capnp.h, *.po, uv.lock, *.onnx, *.pem, */c_generated_code/*, docs/assets/*, openpilot/tools/plotjuggler/layouts/*, openpilot/selfdrive/assets/offroad/mici_fcc.html, openpilot/starpilot/galaxy/web/vendor/vue/vue.esm-browser.js, openpilot/starpilot/ui/assets/fonts/notices/Unifont-COPYING.txt, openpilot/starpilot/companion/ios/GalaxyBluetooth/Resources/Web/vendor/vue/vue.esm-browser.js, openpilot/starpilot/galaxy_bluetooth/vendor/*, openpilot/starpilot/soloist/pulseaudio/licenses/*, openpilot/starpilot/companion/android/LICENSE.gradle" ignore-regex = "scale\\.numer" # codespell:ignore numer # https://docs.astral.sh/ruff/configuration/#using-pyprojecttoml @@ -150,6 +150,13 @@ lint.ignore = [ ] line-length = 160 lint.flake8-implicit-str-concat.allow-multiline = false +extend-exclude = ["openpilot/starpilot/galaxy_bluetooth/vendor"] # unmodified third-party sources + +[tool.ruff.lint.per-file-ignores] +# dbus-next declares D-Bus signatures as string annotations ('s', 'ay', 'a{sv}'). +"openpilot/starpilot/galaxy_bluetooth/bridge/server.py" = ["F722", "F821"] +# These scripts embed Swift test sources verbatim. +"openpilot/starpilot/companion/ios/tests/*.py" = ["E501"] [tool.ruff.lint.flake8-tidy-imports.banned-api] "time.time".msg = "Use time.monotonic. time.time can skip due to its reference clock, you probably want a monotonic clock" @@ -162,6 +169,9 @@ lint.flake8-implicit-str-concat.allow-multiline = false [tool.ruff.format] quote-style = "preserve" +[tool.ty.src] +exclude = ["openpilot/starpilot/galaxy_bluetooth/vendor"] # unmodified third-party sources + [tool.ty.environment] extra-paths = ["opendbc_repo", "msgq_repo", "rednose_repo", "tinygrad_repo", "teleoprtc_repo", "jetlink_repo"] @@ -169,6 +179,11 @@ extra-paths = ["opendbc_repo", "msgq_repo", "rednose_repo", "tinygrad_repo", "te unresolved-import = "ignore" # Cython-compiled modules (.pyx) unresolved-attribute = "ignore" # many from capnp and Cython modules +[[tool.ty.overrides]] +# dbus-next declares D-Bus signatures as string annotations ('s', 'ay', 'a{sv}'). +include = ["openpilot/starpilot/galaxy_bluetooth/bridge/server.py"] +rules = { unresolved-reference = "ignore", invalid-syntax-in-forward-annotation = "ignore" } + [tool.uv] python-preference = "only-managed" default-groups = ["standalone"] diff --git a/scripts/lint/check_added_large_files.py b/scripts/lint/check_added_large_files.py index e5c6ea792d..0173cb6569 100755 --- a/scripts/lint/check_added_large_files.py +++ b/scripts/lint/check_added_large_files.py @@ -9,6 +9,8 @@ LARGE_TEXT_FILES = frozenset(( # shortcut: these existing modules bypass 120 KiB; split when their responsibilities warrant it. 'openpilot/selfdrive/selfdrived/selfdrived.py', 'openpilot/starpilot/galaxy/server.py', + 'openpilot/starpilot/galaxy/web/js/onroad-layout.js', + 'openpilot/starpilot/companion/ios/GalaxyBluetooth/Resources/Web/js/onroad-layout.js', 'openpilot/cereal/gen/cpp/car.capnp.c++', 'openpilot/cereal/gen/cpp/car.capnp.h', 'openpilot/cereal/gen/cpp/custom.capnp.c++', diff --git a/scripts/lint/lint.sh b/scripts/lint/lint.sh index 4bd13b2bb8..3be20bc224 100755 --- a/scripts/lint/lint.sh +++ b/scripts/lint/lint.sh @@ -112,7 +112,8 @@ PYTHON_FILES=() while IFS= read -r -d '' f; do if [[ -f $f ]]; then ALL_FILES+=("$f") - if [[ $f == *.py ]]; then + # Vendored third-party sources keep their upstream indentation. + if [[ $f == *.py && $f != openpilot/starpilot/galaxy_bluetooth/vendor/* ]]; then PYTHON_FILES+=("$f") fi fi