diff -Nru influxdb-1.0.2+dfsg1/appveyor.yml influxdb-1.1.1+dfsg1/appveyor.yml --- influxdb-1.0.2+dfsg1/appveyor.yml 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/appveyor.yml 2016-12-06 21:36:15.000000000 +0000 @@ -12,13 +12,13 @@ # Environment variables environment: - #AppVeyor has go 1.6 as default go environment - GOROOT: C:\go + GOROOT: C:\go17 GOPATH: C:\gopath # Scripts that run after cloning repository install: - set PATH=%GOROOT%\bin;%GOPATH%\bin;%PATH% + - rmdir c:\go /s /q - echo %PATH% - echo %GOPATH% - cd C:\gopath\src\github.com\influxdata\influxdb @@ -28,10 +28,10 @@ - cd C:\gopath\src\github.com\influxdata\influxdb - gdm restore -# To run your custom scripts instead of automatic MSBuild +# To run your custom scripts instead of automatic MSBuild build_script: - go get -t -v ./... - go test -race -v ./... - + # To disable deployment deploy: off diff -Nru influxdb-1.0.2+dfsg1/build-docker.sh influxdb-1.1.1+dfsg1/build-docker.sh --- influxdb-1.0.2+dfsg1/build-docker.sh 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/build-docker.sh 2016-12-06 21:36:15.000000000 +0000 @@ -2,7 +2,7 @@ set -e -x -GO_VER=${GO_VER:-1.4.3} +GO_VER=${GO_VER:-1.7.4} docker run -it -v "${GOPATH}":/gopath -v "$(pwd)":/app -e "GOPATH=/gopath" -w /app golang:$GO_VER sh -c 'CGO_ENABLED=0 go build -a --installsuffix cgo --ldflags="-s" -o influxd ./cmd/influxd' diff -Nru influxdb-1.0.2+dfsg1/build.py influxdb-1.1.1+dfsg1/build.py --- influxdb-1.0.2+dfsg1/build.py 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/build.py 2016-12-06 21:36:15.000000000 +0000 @@ -49,7 +49,7 @@ DESCRIPTION = "Distributed time-series database." prereqs = [ 'git', 'go' ] -go_vet_command = "go tool vet -example=false ./" +go_vet_command = "go tool vet ./" optional_prereqs = [ 'fpm', 'rpmbuild', 'gpg' ] fpm_common_args = "-f -s dir --log error \ @@ -154,7 +154,7 @@ run("make -C man/ clean install DESTDIR={}/usr".format(build_root)) for path, dir, files in os.walk(os.path.join(build_root, MAN_DIR[1:])): for f in files: - run("gzip {}".format(os.path.join(path, f))) + run("gzip -9n {}".format(os.path.join(path, f))) def run_generate(): """Run 'go generate' to rebuild any static assets. diff -Nru influxdb-1.0.2+dfsg1/CHANGELOG.md influxdb-1.1.1+dfsg1/CHANGELOG.md --- influxdb-1.0.2+dfsg1/CHANGELOG.md 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/CHANGELOG.md 2016-12-06 21:36:15.000000000 +0000 @@ -1,3 +1,111 @@ +## v1.1.1 [2016-12-06] + +### Features + +- [#7684](https://github.com/influxdata/influxdb/issues/7684): Update Go version to 1.7.4. + +### Bugfixes + +- [#7625](https://github.com/influxdata/influxdb/issues/7625): Fix incorrect tag value in error message. +- [#7661](https://github.com/influxdata/influxdb/pull/7661): Quote the empty string as an ident. +- [#7679](https://github.com/influxdata/influxdb/pull/7679): Fix string fields w/ trailing slashes + +### Security + +[Go 1.7.4](https://golang.org/doc/devel/release.html#go1.7.minor) was released to address two security issues. This release includes these security fixes. + +## v1.1.0 [2016-11-14] + +### Release Notes + +This release is built with go 1.7.3 and provides many performance optimizations, stability changes and a few new query capabilities. If upgrading from a prior version, please read the configuration changes below section before upgrading. + +### Deprecations + +The admin interface is deprecated and will be removed in a subsequent release. The configuration setting to enable the admin UI is now disabled by default, but can be enabled if necessary. We recommend using [Chronograf](https://github.com/influxdata/chronograf) or [Grafana](https://github.com/grafana/grafana) as a replacement. + +### Configuration Changes + +The following configuration changes may need to changed before upgrading to `1.1.0` from prior versions. + +#### `[admin]` Section + +* `enabled` now default to false. If you are currently using the admin interaface, you will need to change this value to `true` to re-enable it. The admin interface is currently deprecated and will be removed in a subsequent release. + +#### `[data]` Section + +* `max-values-per-tag` was added with a default of 100,000, but can be disabled by setting it to `0`. Existing measurements with tags that exceed this limit will continue to load, but writes that would cause the tags cardinality to increase will be dropped and a `partial write` error will be returned to the caller. This limit can be used to prevent high cardinality tag values from being written to a measurement. +* `cache-max-memory-size` has been increased to from `524288000` to `1048576000`. This setting is the maximum amount of RAM, in bytes, a shard cache can use before it rejects writes with an error. Setting this value to `0` disables the limit. +* `cache-snapshot-write-cold-duration` has been decreased from `1h` to `10m`. This setting determines how long values will stay in the shard cache while the shard is cold for writes. +* `compact-full-write-cold-duration` has been decreased from `24h` to `4h`. The shorter duration allows cold shards to be compacted to an optimal state more quickly. + +### Features + +The query language has been extended with a few new features: + +* New `cumulative_sum` function - [#7388](https://github.com/influxdata/influxdb/pull/7388) +* New `linear` fill option - [#7408](https://github.com/influxdata/influxdb/pull/7408) +* Support `ON` for `SHOW` commands - [#7295](https://github.com/influxdata/influxdb/pull/7295) +* Support regex on fields keys in select clause - [#7442](https://github.com/influxdata/influxdb/pull/7442) + +All Changes: + +- [#7415](https://github.com/influxdata/influxdb/pull/7415): Add sample function to query language. +- [#7403](https://github.com/influxdata/influxdb/pull/7403): Add `fill(linear)` to query language. +- [#7120](https://github.com/influxdata/influxdb/issues/7120): Add additional statistics to query executor. +- [#7135](https://github.com/influxdata/influxdb/pull/7135): Support enable HTTP service over unix domain socket. Thanks @oiooj +- [#3634](https://github.com/influxdata/influxdb/issues/3634): Support mixed duration units. +- [#7099](https://github.com/influxdata/influxdb/pull/7099): Implement text/csv content encoding for the response writer. +- [#6992](https://github.com/influxdata/influxdb/issues/6992): Support tools for running async queries. +- [#7136](https://github.com/influxdata/influxdb/pull/7136): Update jwt-go dependency to version 3. +- [#6962](https://github.com/influxdata/influxdb/issues/6962): Support ON and use default database for SHOW commands. +- [#7268](https://github.com/influxdata/influxdb/pull/7268): More man pages for the other tools we package and compress man pages fully. +- [#7305](https://github.com/influxdata/influxdb/pull/7305): UDP Client: Split large points. Thanks @vlasad +- [#7115](https://github.com/influxdata/influxdb/issues/7115): Feature request: `influx inspect -export` should dump WAL files. +- [#7388](https://github.com/influxdata/influxdb/pull/7388): Implement cumulative_sum() function. +- [#7441](https://github.com/influxdata/influxdb/pull/7441): Speed up shutdown by closing shards concurrently. +- [#7146](https://github.com/influxdata/influxdb/issues/7146): Add max-values-per-tag to limit high tag cardinality data +- [#5955](https://github.com/influxdata/influxdb/issues/5955): Make regex work on field and dimension keys in SELECT clause. +- [#7470](https://github.com/influxdata/influxdb/pull/7470): Reduce map allocations when computing the TagSet of a measurement. +- [#6894](https://github.com/influxdata/influxdb/issues/6894): Support `INFLUX_USERNAME` and `INFLUX_PASSWORD` for setting username/password in the CLI. +- [#6896](https://github.com/influxdata/influxdb/issues/6896): Correctly read in input from a non-interactive stream for the CLI. +- [#7463](https://github.com/influxdata/influxdb/pull/7463): Make input plugin services open/close idempotent. +- [#7473](https://github.com/influxdata/influxdb/pull/7473): Align binary math expression streams by time. +- [#7281](https://github.com/influxdata/influxdb/pull/7281): Add stats for active compactions, compaction errors. +- [#7496](https://github.com/influxdata/influxdb/pull/7496): Filter out series within shards that do not have data for that series. +- [#7480](https://github.com/influxdata/influxdb/pull/7480): Improve compaction planning performance by caching tsm file stats. +- [#7320](https://github.com/influxdata/influxdb/issues/7320): Update defaults in config for latest best practices +- [#7495](https://github.com/influxdata/influxdb/pull/7495): Rewrite regexes of the form host = /^server-a$/ to host = 'server-a', to take advantage of the tsdb index. +- [#6704](https://github.com/influxdata/influxdb/issues/6704): Optimize first/last when no group by interval is present. +- [#4461](https://github.com/influxdata/influxdb/issues/4461): Change default time boundaries for raw queries. + +### Bugfixes + +- [#7392](https://github.com/influxdata/influxdb/pull/7392): Enable https subscriptions to work with custom CA certificates. +- [#1834](https://github.com/influxdata/influxdb/issues/1834): Drop time when used as a tag or field key. +- [#7152](https://github.com/influxdata/influxdb/issues/7152): Decrement number of measurements only once when deleting the last series from a measurement. +- [#7177](https://github.com/influxdata/influxdb/issues/7177): Fix base64 encoding issue with /debug/vars stats. +- [#7196](https://github.com/influxdata/influxdb/issues/7196): Fix mmap dereferencing, fixes #7183, #7180 +- [#7013](https://github.com/influxdata/influxdb/issues/7013): Fix the dollar sign so it properly handles reserved keywords. +- [#7297](https://github.com/influxdata/influxdb/issues/7297): Use consistent column output from the CLI for column formatted responses. +- [#7231](https://github.com/influxdata/influxdb/issues/7231): Duplicate parsing bug in ALTER RETENTION POLICY. +- [#7285](https://github.com/influxdata/influxdb/issues/7285): Correctly use password-type field in Admin UI. Thanks @dandv! +- [#2792](https://github.com/influxdata/influxdb/issues/2792): Exceeding max retention policy duration gives incorrect error message +- [#7226](https://github.com/influxdata/influxdb/issues/7226): Fix database locked up when deleting shards +- [#7382](https://github.com/influxdata/influxdb/issues/7382): Shard stats include wal path tag so disk bytes make more sense. +- [#7385](https://github.com/influxdata/influxdb/pull/7385): Reduce query planning allocations +- [#7436](https://github.com/influxdata/influxdb/issues/7436): Remove accidentally added string support for the stddev call. +- [#7161](https://github.com/influxdata/influxdb/issues/7161): Drop measurement causes cache max memory exceeded error. +- [#7334](https://github.com/influxdata/influxdb/issues/7334): Panic with unread show series iterators during drop database +- [#7482](https://github.com/influxdata/influxdb/issues/7482): Fix issue where point would be written to wrong shard. +- [#7431](https://github.com/influxdata/influxdb/issues/7431): Remove /data/process_continuous_queries endpoint. +- [#7053](https://github.com/influxdata/influxdb/issues/7053): Delete statement returns an error when retention policy or database is specified +- [#7494](https://github.com/influxdata/influxdb/issues/7494): influx_inspect: export does not escape field keys. +- [#7526](https://github.com/influxdata/influxdb/issues/7526): Truncate the version string when linking to the documentation. +- [#7548](https://github.com/influxdata/influxdb/issues/7548): Fix output duration units for SHOW QUERIES. +- [#7564](https://github.com/influxdata/influxdb/issues/7564): Fix incorrect grouping when multiple aggregates are used with sparse data. +- [#7606](https://github.com/influxdata/influxdb/pull/7606): Avoid deadlock when `max-row-limit` is hit. + ## v1.0.2 [2016-10-05] ### Bugfixes @@ -21,7 +129,7 @@ - [#7226](https://github.com/influxdata/influxdb/issues/7226): Fix database locked up when deleting shards - [#7315](https://github.com/influxdata/influxdb/issues/7315): Prevent users from manually using system queries since incorrect use would result in a panic. -## v1.0.0 [2016-09-07] +## v1.0.0 [2016-09-08] ### Release Notes @@ -72,7 +180,7 @@ - [#7011](https://github.com/influxdata/influxdb/issues/7011): Create man pages for commands. - [#7050](https://github.com/influxdata/influxdb/pull/7050): Update go package library dependencies. - [#5750](https://github.com/influxdata/influxdb/issues/5750): Support wildcards in aggregate functions. -- [#7605](https://github.com/influxdata/influxdb/issues/7605): Remove IF EXISTS/IF NOT EXISTS from influxql language. +- [#7065](https://github.com/influxdata/influxdb/issues/7065): Remove IF EXISTS/IF NOT EXISTS from influxql language. - [#7095](https://github.com/influxdata/influxdb/pull/7095): Add MaxSeriesPerDatabase config setting. - [#7199](https://github.com/influxdata/influxdb/pull/7199): Add mode function. Thanks @agaurav. - [#7194](https://github.com/influxdata/influxdb/issues/7194): Support negative timestamps for the query engine. @@ -149,6 +257,7 @@ - [#7025](https://github.com/influxdata/influxdb/issues/7025): Move the CQ interval by the group by offset. - [#7125](https://github.com/influxdata/influxdb/pull/7125): Ensure gzip writer is closed in influx_inspect export - [#7127](https://github.com/influxdata/influxdb/pull/7127): Concurrent series limit +- [#7119](https://github.com/influxdata/influxdb/pull/7119): Fix CREATE DATABASE when dealing with default values. - [#7218](https://github.com/influxdata/influxdb/issues/7218): Fix alter retention policy when all options are used. - [#7225](https://github.com/influxdata/influxdb/issues/7225): runtime: goroutine stack exceeds 1000000000-byte limit - [#7240](https://github.com/influxdata/influxdb/issues/7240): Allow blank lines in the line protocol input. @@ -528,7 +637,7 @@ - Scripts are now located in `/usr/lib/influxdb/scripts` (previously `/opt/influxdb`) ### Features -- [#4098](https://github.com/influxdata/influxdb/pull/4702): Support 'history' command at CLI +- [#4702](https://github.com/influxdata/influxdb/pull/4702): Support 'history' command at CLI - [#4098](https://github.com/influxdata/influxdb/issues/4098): Enable `golint` on the code base - uuid subpackage - [#4141](https://github.com/influxdata/influxdb/pull/4141): Control whether each query should be logged - [#4065](https://github.com/influxdata/influxdb/pull/4065): Added precision support in cmd client. Thanks @sbouchex diff -Nru influxdb-1.0.2+dfsg1/circle.yml influxdb-1.1.1+dfsg1/circle.yml --- influxdb-1.0.2+dfsg1/circle.yml 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/circle.yml 2016-12-06 21:36:15.000000000 +0000 @@ -2,7 +2,7 @@ services: - docker environment: - GODIST: "go1.6.2.linux-amd64.tar.gz" + GODIST: "go1.7.4.linux-amd64.tar.gz" post: - mkdir -p download - test -e download/$GODIST || curl -o download/$GODIST https://storage.googleapis.com/golang/$GODIST diff -Nru influxdb-1.0.2+dfsg1/client/influxdb.go influxdb-1.1.1+dfsg1/client/influxdb.go --- influxdb-1.0.2+dfsg1/client/influxdb.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/client/influxdb.go 2016-12-06 21:36:15.000000000 +0000 @@ -586,7 +586,7 @@ // MarshalString renders string representation of a Point with specified // precision. The default precision is nanoseconds. func (p *Point) MarshalString() string { - pt, err := models.NewPoint(p.Measurement, p.Tags, p.Fields, p.Time) + pt, err := models.NewPoint(p.Measurement, models.NewTags(p.Tags), p.Fields, p.Time) if err != nil { return "# ERROR: " + err.Error() + " " + p.Measurement } diff -Nru influxdb-1.0.2+dfsg1/client/README.md influxdb-1.1.1+dfsg1/client/README.md --- influxdb-1.0.2+dfsg1/client/README.md 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/client/README.md 2016-12-06 21:36:15.000000000 +0000 @@ -255,6 +255,28 @@ } ``` +### Point Splitting + +The UDP client now supports splitting single points that exceed the configured +payload size. The logic for processing each point is listed here, starting with +an empty payload. + +1. If adding the point to the current (non-empty) payload would exceed the + configured size, send the current payload. Otherwise, add it to the current + payload. +1. If the point is smaller than the configured size, add it to the payload. +1. If the point has no timestamp, just try to send the entire point as a single + UDP payload, and process the next point. +1. Since the point has a timestamp, re-use the existing measurement name, + tagset, and timestamp and create multiple new points by splitting up the + fields. The per-point length will be kept close to the configured size, + staying under it if possible. This does mean that one large field, maybe a + long string, could be sent as a larger-than-configured payload. + +The above logic attempts to respect configured payload sizes, but not sacrifice +any data integrity. Points without a timestamp can't be split, as that may +cause fields to have differing timestamps when processed by the server. + ## Go Docs Please refer to diff -Nru influxdb-1.0.2+dfsg1/client/v2/client.go influxdb-1.1.1+dfsg1/client/v2/client.go --- influxdb-1.0.2+dfsg1/client/v2/client.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/client/v2/client.go 2016-12-06 21:36:15.000000000 +0000 @@ -7,7 +7,6 @@ "errors" "fmt" "io/ioutil" - "net" "net/http" "net/url" "time" @@ -15,12 +14,6 @@ "github.com/influxdata/influxdb/models" ) -// UDPPayloadSize is a reasonable default payload size for UDP packets that -// could be travelling over the internet. -const ( - UDPPayloadSize = 512 -) - // HTTPConfig is the config data needed to create an HTTP Client type HTTPConfig struct { // Addr should be of the form "http://host:port" @@ -48,17 +41,6 @@ TLSConfig *tls.Config } -// UDPConfig is the config data needed to create a UDP Client -type UDPConfig struct { - // Addr should be of the form "host:port" - // or "[ipv6-host%zone]:port". - Addr string - - // PayloadSize is the maximum size of a UDP client message, optional - // Tune this based on your network. Defaults to UDPBufferSize. - PayloadSize int -} - // BatchPointsConfig is the config data needed to create an instance of the BatchPoints struct type BatchPointsConfig struct { // Precision is the write precision of the points, defaults to "ns" @@ -76,7 +58,8 @@ // Client is a client interface for writing & querying the database type Client interface { - // Ping checks that status of cluster + // Ping checks that status of cluster, and will always return 0 time and no + // error for UDP clients Ping(timeout time.Duration) (time.Duration, string, error) // Write takes a BatchPoints object and writes all Points to InfluxDB. @@ -177,42 +160,6 @@ return nil } -// NewUDPClient returns a client interface for writing to an InfluxDB UDP -// service from the given config. -func NewUDPClient(conf UDPConfig) (Client, error) { - var udpAddr *net.UDPAddr - udpAddr, err := net.ResolveUDPAddr("udp", conf.Addr) - if err != nil { - return nil, err - } - - conn, err := net.DialUDP("udp", nil, udpAddr) - if err != nil { - return nil, err - } - - payloadSize := conf.PayloadSize - if payloadSize == 0 { - payloadSize = UDPPayloadSize - } - - return &udpclient{ - conn: conn, - payloadSize: payloadSize, - }, nil -} - -// Ping will check to see if the server is up with an optional timeout on waiting for leader. -// Ping returns how long the request took, the version of the server it connected to, and an error if one occurred. -func (uc *udpclient) Ping(timeout time.Duration) (time.Duration, string, error) { - return 0, "", nil -} - -// Close releases the udpclient's resources. -func (uc *udpclient) Close() error { - return uc.conn.Close() -} - // client is safe for concurrent use as the fields are all read-only // once the client is instantiated. type client struct { @@ -226,11 +173,6 @@ transport *http.Transport } -type udpclient struct { - conn *net.UDPConn - payloadSize int -} - // BatchPoints is an interface into a batched grouping of points to write into // InfluxDB together. BatchPoints is NOT thread-safe, you must create a separate // batch for each goroutine. @@ -356,7 +298,7 @@ T = t[0] } - pt, err := models.NewPoint(name, tags, fields, T) + pt, err := models.NewPoint(name, models.NewTags(tags), fields, T) if err != nil { return nil, err } @@ -382,7 +324,7 @@ // Tags returns the tags associated with the point func (p *Point) Tags() map[string]string { - return p.pt.Tags() + return p.pt.Tags().Map() } // Time return the timestamp for the point @@ -405,31 +347,6 @@ return &Point{pt: pt} } -func (uc *udpclient) Write(bp BatchPoints) error { - var b bytes.Buffer - var d time.Duration - d, _ = time.ParseDuration("1" + bp.Precision()) - - for _, p := range bp.Points() { - pointstring := p.pt.RoundedString(d) + "\n" - - // Write and reset the buffer if we reach the max size - if b.Len()+len(pointstring) >= uc.payloadSize { - if _, err := uc.conn.Write(b.Bytes()); err != nil { - return err - } - b.Reset() - } - - if _, err := b.WriteString(pointstring); err != nil { - return err - } - } - - _, err := uc.conn.Write(b.Bytes()) - return err -} - func (c *client) Write(bp BatchPoints) error { var b bytes.Buffer @@ -532,10 +449,6 @@ Err string `json:"error,omitempty"` } -func (uc *udpclient) Query(q Query) (*Response, error) { - return nil, fmt.Errorf("Querying via UDP is not supported") -} - // Query sends a command to the server and returns the Response func (c *client) Query(q Query) (*Response, error) { u := c.url diff -Nru influxdb-1.0.2+dfsg1/client/v2/client_test.go influxdb-1.1.1+dfsg1/client/v2/client_test.go --- influxdb-1.0.2+dfsg1/client/v2/client_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/client/v2/client_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -72,6 +72,68 @@ } } +func TestUDPClient_Batches(t *testing.T) { + var logger writeLogger + var cl udpclient + + cl.conn = &logger + cl.payloadSize = 20 // should allow for two points per batch + + // expected point should look like this: "cpu a=1i" + fields := map[string]interface{}{"a": 1} + + p, _ := NewPoint("cpu", nil, fields, time.Time{}) + + bp, _ := NewBatchPoints(BatchPointsConfig{}) + + for i := 0; i < 9; i++ { + bp.AddPoint(p) + } + + if err := cl.Write(bp); err != nil { + t.Fatalf("Unexpected error during Write: %v", err) + } + + if len(logger.writes) != 5 { + t.Errorf("Mismatched write count: got %v, exp %v", len(logger.writes), 5) + } +} + +func TestUDPClient_Split(t *testing.T) { + var logger writeLogger + var cl udpclient + + cl.conn = &logger + cl.payloadSize = 1 // force one field per point + + fields := map[string]interface{}{"a": 1, "b": 2, "c": 3, "d": 4} + + p, _ := NewPoint("cpu", nil, fields, time.Unix(1, 0)) + + bp, _ := NewBatchPoints(BatchPointsConfig{}) + + bp.AddPoint(p) + + if err := cl.Write(bp); err != nil { + t.Fatalf("Unexpected error during Write: %v", err) + } + + if len(logger.writes) != len(fields) { + t.Errorf("Mismatched write count: got %v, exp %v", len(logger.writes), len(fields)) + } +} + +type writeLogger struct { + writes [][]byte +} + +func (w *writeLogger) Write(b []byte) (int, error) { + w.writes = append(w.writes, append([]byte(nil), b...)) + return len(b), nil +} + +func (w *writeLogger) Close() error { return nil } + func TestClient_Query(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data Response diff -Nru influxdb-1.0.2+dfsg1/client/v2/udp.go influxdb-1.1.1+dfsg1/client/v2/udp.go --- influxdb-1.0.2+dfsg1/client/v2/udp.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/client/v2/udp.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,112 @@ +package client + +import ( + "fmt" + "io" + "net" + "time" +) + +const ( + // UDPPayloadSize is a reasonable default payload size for UDP packets that + // could be travelling over the internet. + UDPPayloadSize = 512 +) + +// UDPConfig is the config data needed to create a UDP Client +type UDPConfig struct { + // Addr should be of the form "host:port" + // or "[ipv6-host%zone]:port". + Addr string + + // PayloadSize is the maximum size of a UDP client message, optional + // Tune this based on your network. Defaults to UDPPayloadSize. + PayloadSize int +} + +// NewUDPClient returns a client interface for writing to an InfluxDB UDP +// service from the given config. +func NewUDPClient(conf UDPConfig) (Client, error) { + var udpAddr *net.UDPAddr + udpAddr, err := net.ResolveUDPAddr("udp", conf.Addr) + if err != nil { + return nil, err + } + + conn, err := net.DialUDP("udp", nil, udpAddr) + if err != nil { + return nil, err + } + + payloadSize := conf.PayloadSize + if payloadSize == 0 { + payloadSize = UDPPayloadSize + } + + return &udpclient{ + conn: conn, + payloadSize: payloadSize, + }, nil +} + +// Close releases the udpclient's resources. +func (uc *udpclient) Close() error { + return uc.conn.Close() +} + +type udpclient struct { + conn io.WriteCloser + payloadSize int +} + +func (uc *udpclient) Write(bp BatchPoints) error { + var b = make([]byte, 0, uc.payloadSize) // initial buffer size, it will grow as needed + var d, _ = time.ParseDuration("1" + bp.Precision()) + + var delayedError error + + var checkBuffer = func(n int) { + if len(b) > 0 && len(b)+n > uc.payloadSize { + if _, err := uc.conn.Write(b); err != nil { + delayedError = err + } + b = b[:0] + } + } + + for _, p := range bp.Points() { + p.pt.Round(d) + pointSize := p.pt.StringSize() + 1 // include newline in size + //point := p.pt.RoundedString(d) + "\n" + + checkBuffer(pointSize) + + if p.Time().IsZero() || pointSize <= uc.payloadSize { + b = p.pt.AppendString(b) + b = append(b, '\n') + continue + } + + points := p.pt.Split(uc.payloadSize - 1) // account for newline character + for _, sp := range points { + checkBuffer(sp.StringSize() + 1) + b = sp.AppendString(b) + b = append(b, '\n') + } + } + + if len(b) > 0 { + if _, err := uc.conn.Write(b); err != nil { + return err + } + } + return delayedError +} + +func (uc *udpclient) Query(q Query) (*Response, error) { + return nil, fmt.Errorf("Querying via UDP is not supported") +} + +func (uc *udpclient) Ping(timeout time.Duration) (time.Duration, string, error) { + return 0, "", nil +} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx/cli/cli.go influxdb-1.1.1+dfsg1/cmd/influx/cli/cli.go --- influxdb-1.0.2+dfsg1/cmd/influx/cli/cli.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx/cli/cli.go 2016-12-06 21:36:15.000000000 +0000 @@ -7,6 +7,7 @@ "errors" "fmt" "io" + "io/ioutil" "net" "net/url" "os" @@ -18,6 +19,8 @@ "syscall" "text/tabwriter" + "golang.org/x/crypto/ssh/terminal" + "github.com/influxdata/influxdb/client" "github.com/influxdata/influxdb/importer/v8" "github.com/influxdata/influxdb/models" @@ -58,6 +61,7 @@ Chunked bool Quit chan struct{} IgnoreSignals bool // Ignore signals normally caught by this process (used primarily for testing) + ForceTTY bool // Force the CLI to act as if it were connected to a TTY osSignals chan os.Signal historyFilePath string } @@ -73,10 +77,7 @@ // Run executes the CLI func (c *CommandLine) Run() error { - if !c.IgnoreSignals { - // register OS signals for graceful termination - signal.Notify(c.osSignals, syscall.SIGINT, syscall.SIGTERM) - } + hasTTY := c.ForceTTY || terminal.IsTerminal(int(os.Stdin.Fd())) var promptForPassword bool // determine if they set the password flag but provided no value @@ -88,18 +89,29 @@ } } - c.Line = liner.NewLiner() - defer c.Line.Close() - - c.Line.SetMultiLineMode(true) + // Check if we will be able to prompt for the password later. + if promptForPassword && !hasTTY { + return errors.New("Unable to prompt for a password with no TTY.") + } + // Read environment variables for username/password. + if c.Username == "" { + c.Username = os.Getenv("INFLUX_USERNAME") + } + // If we are going to be prompted for a password, always use the entered password. if promptForPassword { - p, e := c.Line.PasswordPrompt("password: ") + // Open the liner (temporarily) and prompt for the password. + p, e := func() (string, error) { + l := liner.NewLiner() + defer l.Close() + return l.PasswordPrompt("password: ") + }() if e != nil { - fmt.Println("Unable to parse password.") - } else { - c.Password = p + return errors.New("Unable to parse password") } + c.Password = p + } else if c.Password == "" { + c.Password = os.Getenv("INFLUX_PASSWORD") } if err := c.Connect(""); err != nil { @@ -111,17 +123,6 @@ // Modify precision. c.SetPrecision(c.Precision) - if c.Execute == "" && !c.Import { - token, err := c.DatabaseToken() - if err != nil { - return fmt.Errorf("Failed to check token: %s", err.Error()) - } - if token == "" { - fmt.Printf(noTokenMsg) - } - fmt.Printf("Connected to %s version %s\n", c.Client.Addr(), c.ServerVersion) - } - if c.Execute != "" { // Make the non-interactive mode send everything through the CLI's parser // the same way the interactive mode works @@ -131,8 +132,6 @@ return err } } - - c.Line.Close() return nil } @@ -158,13 +157,38 @@ i := v8.NewImporter(config) if err := i.Import(); err != nil { err = fmt.Errorf("ERROR: %s\n", err) - c.Line.Close() return err } - c.Line.Close() return nil } + if !hasTTY { + cmd, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return err + } + return c.ExecuteQuery(string(cmd)) + } + + if !c.IgnoreSignals { + // register OS signals for graceful termination + signal.Notify(c.osSignals, syscall.SIGINT, syscall.SIGTERM) + } + + c.Line = liner.NewLiner() + defer c.Line.Close() + + c.Line.SetMultiLineMode(true) + + token, err := c.DatabaseToken() + if err != nil { + return fmt.Errorf("Failed to check token: %s", err.Error()) + } + if token == "" { + fmt.Printf(noTokenMsg) + } + fmt.Printf("Connected to %s version %s\n", c.Client.Addr(), c.ServerVersion) + c.Version() // Only load/write history if HOME environment variable is set. @@ -200,7 +224,7 @@ c.exit() return e } - if err := c.ParseCommand(l); err != ErrBlankCommand { + if err := c.ParseCommand(l); err != ErrBlankCommand && !strings.HasPrefix(strings.TrimSpace(l), "auth") { c.Line.AppendHistory(l) c.saveHistory() } @@ -570,7 +594,8 @@ if err != nil { return "", err } - if response.Error() != nil || len((*response).Results[0].Series) == 0 { + + if response.Error() != nil || len(response.Results) == 0 || len(response.Results[0].Series) == 0 { return "", nil } @@ -645,7 +670,7 @@ // formatResults will behave differently if you are formatting for columns or csv func (c *CommandLine) formatResults(result client.Result, separator string) []string { rows := []string{} - // Create a tabbed writer for each result a they won't always line up + // Create a tabbed writer for each result as they won't always line up for i, row := range result.Series { // gather tags tags := []string{} @@ -676,15 +701,11 @@ rows = append(rows, "") } - // If we are column format, we break out the name/tag to seperate lines + // If we are column format, we break out the name/tag to separate lines if c.Format == "column" { if row.Name != "" { n := fmt.Sprintf("name: %s", row.Name) rows = append(rows, n) - if len(tags) == 0 { - l := strings.Repeat("-", len(n)) - rows = append(rows, l) - } } if len(tags) > 0 { t := fmt.Sprintf("tags: %s", (strings.Join(tags, ", "))) @@ -694,8 +715,8 @@ rows = append(rows, strings.Join(columnNames, separator)) - // if format is column, break tags to their own line/format - if c.Format == "column" && len(tags) > 0 { + // if format is column, write dashes under each column + if c.Format == "column" { lines := []string{} for _, columnName := range columnNames { lines = append(lines, strings.Repeat("-", len(columnName))) @@ -719,7 +740,7 @@ } rows = append(rows, strings.Join(values, separator)) } - // Outout a line separator if in column format + // Output a line separator if in column format if c.Format == "column" { rows = append(rows, "") } @@ -745,7 +766,7 @@ // Settings prints current settings func (c *CommandLine) Settings() { w := new(tabwriter.Writer) - w.Init(os.Stdout, 0, 8, 1, '\t', 0) + w.Init(os.Stdout, 0, 1, 1, '\t', 0) if c.Port > 0 { fmt.Fprintf(w, "Host\t%s:%d\n", c.Host, c.Port) } else { diff -Nru influxdb-1.0.2+dfsg1/cmd/influx/cli/cli_test.go influxdb-1.1.1+dfsg1/cmd/influx/cli/cli_test.go --- influxdb-1.0.2+dfsg1/cmd/influx/cli/cli_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx/cli/cli_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -48,6 +48,7 @@ c.Host = h c.Port, _ = strconv.Atoi(p) c.IgnoreSignals = true + c.ForceTTY = true go func() { close(c.Quit) }() @@ -69,6 +70,7 @@ c.Precision = "ms" c.Execute = "INSERT sensor,floor=1 value=2" c.IgnoreSignals = true + c.ForceTTY = true if err := c.Run(); err != nil { t.Fatalf("Run failed with error: %s", err) } diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/help/help.go influxdb-1.1.1+dfsg1/cmd/influxd/help/help.go --- influxdb-1.0.2+dfsg1/cmd/influxd/help/help.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/help/help.go 2016-12-06 21:36:15.000000000 +0000 @@ -41,5 +41,5 @@ "run" is the default command. -Use "influxd help [command]" for more information about a command. +Use "influxd [command] -help" for more information about a command. ` diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/main.go influxdb-1.1.1+dfsg1/cmd/influxd/main.go --- influxdb-1.0.2+dfsg1/cmd/influxd/main.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/main.go 2016-12-06 21:36:15.000000000 +0000 @@ -8,10 +8,10 @@ "math/rand" "os" "os/signal" - "strings" "syscall" "time" + "github.com/influxdata/influxdb/cmd" "github.com/influxdata/influxdb/cmd/influxd/backup" "github.com/influxdata/influxdb/cmd/influxd/help" "github.com/influxdata/influxdb/cmd/influxd/restore" @@ -69,7 +69,7 @@ // Run determines and runs the command specified by the CLI args. func (m *Main) Run(args ...string) error { - name, args := ParseCommandName(args) + name, args := cmd.ParseCommandName(args) // Extract name from args. switch name { @@ -141,31 +141,6 @@ return nil } -// ParseCommandName extracts the command name and args from the args list. -func ParseCommandName(args []string) (string, []string) { - // Retrieve command name as first argument. - var name string - if len(args) > 0 { - if !strings.HasPrefix(args[0], "-") { - name = args[0] - } else if args[0] == "-h" || args[0] == "-help" || args[0] == "--help" { - // Special case -h immediately following binary name - name = "help" - } - } - - // If command is "help" and has an argument then rewrite args to use "-h". - if name == "help" && len(args) > 2 && !strings.HasPrefix(args[1], "-") { - return args[1], []string{"-h"} - } - - // If a named command is specified then return it with its arguments. - if name != "" { - return name, args[1:] - } - return "", args -} - // VersionCommand represents the command executed by "influxd version". type VersionCommand struct { Stdout io.Writer diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/run/command.go influxdb-1.1.1+dfsg1/cmd/influxd/run/command.go --- influxdb-1.0.2+dfsg1/cmd/influxd/run/command.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/run/command.go 2016-12-06 21:36:15.000000000 +0000 @@ -81,9 +81,6 @@ return fmt.Errorf("write pid file: %s", err) } - // Turn on block profiling to debug stuck databases - runtime.SetBlockProfileRate(int(1 * time.Second)) - // Parse config config, err := cmd.ParseConfig(options.GetConfigPath()) if err != nil { @@ -100,6 +97,11 @@ return fmt.Errorf("%s. To generate a valid configuration file run `influxd config > influxdb.generated.conf`", err) } + if config.HTTPD.PprofEnabled { + // Turn on block profiling to debug stuck databases + runtime.SetBlockProfileRate(int(1 * time.Second)) + } + // Create server from config and start it. buildInfo := &BuildInfo{ Version: cmd.Version, diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/run/config.go influxdb-1.1.1+dfsg1/cmd/influxd/run/config.go --- influxdb-1.0.2+dfsg1/cmd/influxd/run/config.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/run/config.go 2016-12-06 21:36:15.000000000 +0000 @@ -106,8 +106,6 @@ c.Data.Dir = filepath.Join(homeDir, ".influxdb/data") c.Data.WALDir = filepath.Join(homeDir, ".influxdb/wal") - c.Admin.Enabled = true - return c, nil } diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/run/server_bench_test.go influxdb-1.1.1+dfsg1/cmd/influxd/run/server_bench_test.go --- influxdb-1.0.2+dfsg1/cmd/influxd/run/server_bench_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/run/server_bench_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -7,25 +7,17 @@ "testing" ) -func BenchmarkServer_Query_Count_1(b *testing.B) { - benchmarkServerQueryCount(b, 1) -} +var strResult string -func BenchmarkServer_Query_Count_1K(b *testing.B) { - benchmarkServerQueryCount(b, 1000) -} - -func BenchmarkServer_Query_Count_100K(b *testing.B) { - benchmarkServerQueryCount(b, 100000) -} - -func BenchmarkServer_Query_Count_1M(b *testing.B) { - benchmarkServerQueryCount(b, 1000000) -} +func BenchmarkServer_Query_Count_1(b *testing.B) { benchmarkServerQueryCount(b, 1) } +func BenchmarkServer_Query_Count_1K(b *testing.B) { benchmarkServerQueryCount(b, 1000) } +func BenchmarkServer_Query_Count_100K(b *testing.B) { benchmarkServerQueryCount(b, 100000) } +func BenchmarkServer_Query_Count_1M(b *testing.B) { benchmarkServerQueryCount(b, 1000000) } func benchmarkServerQueryCount(b *testing.B, pointN int) { - s := OpenDefaultServer(NewConfig()) - defer s.Close() + if _, err := benchServer.Query(`DROP MEASUREMENT cpu`); err != nil { + b.Fatal(err) + } // Write data into server. var buf bytes.Buffer @@ -35,39 +27,92 @@ fmt.Fprint(&buf, "\n") } } - s.MustWrite("db0", "rp0", buf.String(), nil) + benchServer.MustWrite("db0", "rp0", buf.String(), nil) // Query simple count from server. b.ResetTimer() b.ReportAllocs() + var err error for i := 0; i < b.N; i++ { - if results, err := s.Query(`SELECT count(value) FROM db0.rp0.cpu`); err != nil { + if strResult, err = benchServer.Query(`SELECT count(value) FROM db0.rp0.cpu`); err != nil { b.Fatal(err) - } else if results != fmt.Sprintf(`{"results":[{"series":[{"name":"cpu","columns":["time","count"],"values":[["1970-01-01T00:00:00Z",%d]]}]}]}`, pointN) { - b.Fatalf("unexpected result: %s", results) + } else if strResult != fmt.Sprintf(`{"results":[{"series":[{"name":"cpu","columns":["time","count"],"values":[["1970-01-01T00:00:00Z",%d]]}]}]}`, pointN) { + b.Fatalf("unexpected result: %s", strResult) } } } -func BenchmarkServer_ShowSeries_1(b *testing.B) { - benchmarkServerShowSeries(b, 1) +func BenchmarkServer_Query_Count_Where_500(b *testing.B) { + benchmarkServerQueryCountWhere(b, false, 500) } - -func BenchmarkServer_ShowSeries_1K(b *testing.B) { - benchmarkServerShowSeries(b, 1000) +func BenchmarkServer_Query_Count_Where_1K(b *testing.B) { + benchmarkServerQueryCountWhere(b, false, 1000) +} +func BenchmarkServer_Query_Count_Where_10K(b *testing.B) { + benchmarkServerQueryCountWhere(b, false, 10000) +} +func BenchmarkServer_Query_Count_Where_100K(b *testing.B) { + benchmarkServerQueryCountWhere(b, false, 100000) } -func BenchmarkServer_ShowSeries_100K(b *testing.B) { - benchmarkServerShowSeries(b, 100000) +func BenchmarkServer_Query_Count_Where_Regex_500(b *testing.B) { + benchmarkServerQueryCountWhere(b, true, 500) +} +func BenchmarkServer_Query_Count_Where_Regex_1K(b *testing.B) { + benchmarkServerQueryCountWhere(b, true, 1000) +} +func BenchmarkServer_Query_Count_Where_Regex_10K(b *testing.B) { + benchmarkServerQueryCountWhere(b, true, 10000) +} +func BenchmarkServer_Query_Count_Where_Regex_100K(b *testing.B) { + benchmarkServerQueryCountWhere(b, true, 100000) } -func BenchmarkServer_ShowSeries_1M(b *testing.B) { - benchmarkServerShowSeries(b, 1000000) +func benchmarkServerQueryCountWhere(b *testing.B, useRegex bool, pointN int) { + if _, err := benchServer.Query(`DROP MEASUREMENT cpu`); err != nil { + b.Fatal(err) + } + + // Write data into server. + var buf bytes.Buffer + for i := 0; i < pointN; i++ { + fmt.Fprintf(&buf, `cpu,host=server-%d value=100 %d`, i, i) + if i != pointN-1 { + fmt.Fprint(&buf, "\n") + } + } + benchServer.MustWrite("db0", "rp0", buf.String(), nil) + + // Query count from server with WHERE + var ( + err error + condition = `host = 'server-487'` + ) + + if useRegex { + condition = `host =~ /^server-487$/` + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if strResult, err = benchServer.Query(fmt.Sprintf(`SELECT count(value) FROM db0.rp0.cpu WHERE %s`, condition)); err != nil { + b.Fatal(err) + } else if strResult == `{"results":[{}]}` { + b.Fatal("no results") + } + } } +func BenchmarkServer_ShowSeries_1(b *testing.B) { benchmarkServerShowSeries(b, 1) } +func BenchmarkServer_ShowSeries_1K(b *testing.B) { benchmarkServerShowSeries(b, 1000) } +func BenchmarkServer_ShowSeries_100K(b *testing.B) { benchmarkServerShowSeries(b, 100000) } +func BenchmarkServer_ShowSeries_1M(b *testing.B) { benchmarkServerShowSeries(b, 1000000) } + func benchmarkServerShowSeries(b *testing.B, pointN int) { - s := OpenDefaultServer(NewConfig()) - defer s.Close() + if _, err := benchServer.Query(`DROP MEASUREMENT cpu`); err != nil { + b.Fatal(err) + } // Write data into server. var buf bytes.Buffer @@ -77,13 +122,14 @@ fmt.Fprint(&buf, "\n") } } - s.MustWrite("db0", "rp0", buf.String(), nil) + benchServer.MustWrite("db0", "rp0", buf.String(), nil) // Query simple count from server. b.ResetTimer() b.ReportAllocs() + var err error for i := 0; i < b.N; i++ { - if _, err := s.QueryWithParams(`SHOW SERIES`, url.Values{"db": {"db0"}}); err != nil { + if strResult, err = benchServer.QueryWithParams(`SHOW SERIES`, url.Values{"db": {"db0"}}); err != nil { b.Fatal(err) } } diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/run/server.go influxdb-1.1.1+dfsg1/cmd/influxd/run/server.go --- influxdb-1.0.2+dfsg1/cmd/influxd/run/server.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/run/server.go 2016-12-06 21:36:15.000000000 +0000 @@ -267,13 +267,6 @@ srv.Handler.PointsWriter = s.PointsWriter srv.Handler.Version = s.buildInfo.Version - // If a ContinuousQuerier service has been started, attach it. - for _, srvc := range s.Services { - if cqsrvc, ok := srvc.(continuous_querier.ContinuousQuerier); ok { - srv.Handler.ContinuousQuerier = cqsrvc - } - } - s.Services = append(s.Services, srv) } diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/run/server_helpers_test.go influxdb-1.1.1+dfsg1/cmd/influxd/run/server_helpers_test.go --- influxdb-1.0.2+dfsg1/cmd/influxd/run/server_helpers_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/run/server_helpers_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -239,7 +239,6 @@ c.Data.Dir = MustTempFile() c.Data.WALDir = MustTempFile() - c.Data.WALLoggingEnabled = false c.HTTPD.Enabled = true c.HTTPD.BindAddress = "127.0.0.1:0" diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/run/server_suite_test.go influxdb-1.1.1+dfsg1/cmd/influxd/run/server_suite_test.go --- influxdb-1.0.2+dfsg1/cmd/influxd/run/server_suite_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/run/server_suite_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -31,7 +31,7 @@ &Query{ name: "create database should error with bad name", command: `CREATE DATABASE 0xdb0`, - exp: `{"error":"error parsing query: found 0, expected identifier at line 1, char 17"}`, + exp: `{"error":"error parsing query: found 0xdb0, expected identifier at line 1, char 17"}`, }, &Query{ name: "create database with retention duration should error with bad retention duration", @@ -464,7 +464,7 @@ &Query{ name: "show retention policies should return auto-created policy", command: `SHOW RETENTION POLICIES ON db0`, - exp: `{"results":[{"series":[{"columns":["name","duration","shardGroupDuration","replicaN","default"],"values":[["autogen","0","168h0m0s",1,true]]}]}]}`, + exp: `{"results":[{"series":[{"columns":["name","duration","shardGroupDuration","replicaN","default"],"values":[["autogen","0s","168h0m0s",1,true]]}]}]}`, }, }, } diff -Nru influxdb-1.0.2+dfsg1/cmd/influxd/run/server_test.go influxdb-1.1.1+dfsg1/cmd/influxd/run/server_test.go --- influxdb-1.0.2+dfsg1/cmd/influxd/run/server_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influxd/run/server_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -1,9 +1,11 @@ package run_test import ( + "flag" "fmt" "net/http" "net/url" + "os" "strconv" "strings" "testing" @@ -13,6 +15,33 @@ "github.com/influxdata/influxdb/models" ) +// Global server used by benchmarks +var benchServer *Server + +func TestMain(m *testing.M) { + flag.Parse() + + // Setup + c := NewConfig() + c.Retention.Enabled = false + c.Monitor.StoreEnabled = false + c.Meta.LoggingEnabled = false + c.Admin.Enabled = false + c.Subscriber.Enabled = false + c.ContinuousQuery.Enabled = false + c.Data.MaxSeriesPerDatabase = 10000000 // 10M + c.Data.MaxValuesPerTag = 1000000 // 1M + benchServer = OpenDefaultServer(c) + + // Run suite. + r := m.Run() + + // Cleanup + benchServer.Close() + + os.Exit(r) +} + // Ensure that HTTP responses include the InfluxDB version. func TestServer_HTTPResponseVersion(t *testing.T) { version := "v1234" @@ -330,7 +359,7 @@ &Query{ name: "bad create user request", command: `CREATE USER 0xBAD WITH PASSWORD pwd1337`, - exp: `{"error":"error parsing query: found 0, expected identifier at line 1, char 13"}`, + exp: `{"error":"error parsing query: found 0xBAD, expected identifier at line 1, char 13"}`, }, &Query{ name: "bad create user request, no name", @@ -527,7 +556,7 @@ &Query{ name: "default rp exists", command: `show retention policies ON db0`, - exp: `{"results":[{"series":[{"columns":["name","duration","shardGroupDuration","replicaN","default"],"values":[["autogen","0","168h0m0s",1,false],["rp0","0","168h0m0s",1,true]]}]}]}`, + exp: `{"results":[{"series":[{"columns":["name","duration","shardGroupDuration","replicaN","default"],"values":[["autogen","0s","168h0m0s",1,false],["rp0","0s","168h0m0s",1,true]]}]}]}`, }, &Query{ name: "default rp", @@ -924,7 +953,7 @@ &Query{ name: "exceeed max series", command: `SELECT COUNT(value) FROM db0.rp0.cpu`, - exp: `{"results":[{"error":"max select series count exceeded: 4 series"}]}`, + exp: `{"results":[{"error":"max-select-series limit exceeded: (4/3)"}]}`, }, }...) @@ -2421,6 +2450,268 @@ } } +// Ensure the server can handle various group by time cumulative sum queries. +func TestServer_Query_SelectGroupByTimeCumulativeSum(t *testing.T) { + t.Parallel() + s := OpenServer(NewConfig()) + defer s.Close() + + test := NewTest("db0", "rp0") + test.writes = Writes{ + &Write{data: fmt.Sprintf(`cpu value=10 1278010020000000000 +cpu value=15 1278010021000000000 +cpu value=20 1278010022000000000 +cpu value=25 1278010023000000000 +`)}, + } + + test.addQueries([]*Query{ + &Query{ + name: "calculate cumulative sum of count", + command: `SELECT cumulative_sum(count(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",2],["2010-07-01T18:47:02Z",4]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of mean", + command: `SELECT cumulative_sum(mean(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",12.5],["2010-07-01T18:47:02Z",35]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of median", + command: `SELECT cumulative_sum(median(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",12.5],["2010-07-01T18:47:02Z",35]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of mode", + command: `SELECT cumulative_sum(mode(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",30]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of sum", + command: `SELECT cumulative_sum(sum(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",25],["2010-07-01T18:47:02Z",70]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of first", + command: `SELECT cumulative_sum(first(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",30]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of last", + command: `SELECT cumulative_sum(last(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",15],["2010-07-01T18:47:02Z",40]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of min", + command: `SELECT cumulative_sum(min(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",30]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of max", + command: `SELECT cumulative_sum(max(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",15],["2010-07-01T18:47:02Z",40]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of percentile", + command: `SELECT cumulative_sum(percentile(value, 50)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",30]]}]}]}`, + }, + }...) + + for i, query := range test.queries { + if i == 0 { + if err := test.init(s); err != nil { + t.Fatalf("test init failed: %s", err) + } + } + if query.skip { + t.Logf("SKIP:: %s", query.name) + continue + } + if err := query.Execute(s); err != nil { + t.Error(query.Error(err)) + } else if !query.success() { + t.Error(query.failureMessage()) + } + } +} + +// Ensure the server can handle various group by time cumulative sum queries with fill. +func TestServer_Query_SelectGroupByTimeCumulativeSumWithFill(t *testing.T) { + t.Parallel() + s := OpenServer(NewConfig()) + defer s.Close() + + test := NewTest("db0", "rp0") + test.writes = Writes{ + &Write{data: fmt.Sprintf(`cpu value=10 1278010020000000000 +cpu value=20 1278010021000000000 +`)}, + } + + test.addQueries([]*Query{ + &Query{ + name: "calculate cumulative sum of count with fill 0", + command: `SELECT cumulative_sum(count(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",2],["2010-07-01T18:47:02Z",2]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of count with fill previous", + command: `SELECT cumulative_sum(count(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",2],["2010-07-01T18:47:02Z",4]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of mean with fill 0", + command: `SELECT cumulative_sum(mean(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",15],["2010-07-01T18:47:02Z",15]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of mean with fill previous", + command: `SELECT cumulative_sum(mean(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",15],["2010-07-01T18:47:02Z",30]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of median with fill 0", + command: `SELECT cumulative_sum(median(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",15],["2010-07-01T18:47:02Z",15]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of median with fill previous", + command: `SELECT cumulative_sum(median(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",15],["2010-07-01T18:47:02Z",30]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of mode with fill 0", + command: `SELECT cumulative_sum(mode(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",10]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of mode with fill previous", + command: `SELECT cumulative_sum(mode(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",20]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of sum with fill 0", + command: `SELECT cumulative_sum(sum(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",30],["2010-07-01T18:47:02Z",30]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of sum with fill previous", + command: `SELECT cumulative_sum(sum(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",30],["2010-07-01T18:47:02Z",60]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of first with fill 0", + command: `SELECT cumulative_sum(first(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",10]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of first with fill previous", + command: `SELECT cumulative_sum(first(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",20]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of last with fill 0", + command: `SELECT cumulative_sum(last(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",20],["2010-07-01T18:47:02Z",20]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of last with fill previous", + command: `SELECT cumulative_sum(last(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",20],["2010-07-01T18:47:02Z",40]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of min with fill 0", + command: `SELECT cumulative_sum(min(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",10]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of min with fill previous", + command: `SELECT cumulative_sum(min(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",20]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of max with fill 0", + command: `SELECT cumulative_sum(max(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",20],["2010-07-01T18:47:02Z",20]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of max with fill previous", + command: `SELECT cumulative_sum(max(value)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",20],["2010-07-01T18:47:02Z",40]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of percentile with fill 0", + command: `SELECT cumulative_sum(percentile(value, 50)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(0)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",10]]}]}]}`, + }, + &Query{ + name: "calculate cumulative sum of percentile with fill previous", + command: `SELECT cumulative_sum(percentile(value, 50)) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s) fill(previous)`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","cumulative_sum"],"values":[["2010-07-01T18:47:00Z",10],["2010-07-01T18:47:02Z",20]]}]}]}`, + }, + }...) + + for i, query := range test.queries { + if i == 0 { + if err := test.init(s); err != nil { + t.Fatalf("test init failed: %s", err) + } + } + if query.skip { + t.Logf("SKIP:: %s", query.name) + continue + } + if err := query.Execute(s); err != nil { + t.Error(query.Error(err)) + } else if !query.success() { + t.Error(query.failureMessage()) + } + } +} + +func TestServer_Query_SelectGroupByTime_MultipleAggregates(t *testing.T) { + t.Parallel() + s := OpenServer(NewConfig()) + defer s.Close() + + test := NewTest("db0", "rp0") + test.writes = Writes{ + &Write{data: fmt.Sprintf(`test,t=a x=1i 1000000000 +test,t=b y=1i 1000000000 +test,t=a x=2i 2000000000 +test,t=b y=2i 2000000000 +test,t=a x=3i 3000000000 +test,t=b y=3i 3000000000 +`)}, + } + + test.addQueries([]*Query{ + &Query{ + name: "two aggregates with a group by host", + command: `SELECT mean(x) as x, mean(y) as y from db0.rp0.test where time >= 1s and time < 4s group by t, time(1s)`, + exp: `{"results":[{"series":[{"name":"test","tags":{"t":"a"},"columns":["time","x","y"],"values":[["1970-01-01T00:00:01Z",1,null],["1970-01-01T00:00:02Z",2,null],["1970-01-01T00:00:03Z",3,null]]},{"name":"test","tags":{"t":"b"},"columns":["time","x","y"],"values":[["1970-01-01T00:00:01Z",null,1],["1970-01-01T00:00:02Z",null,2],["1970-01-01T00:00:03Z",null,3]]}]}]}`, + }, + }...) + + for i, query := range test.queries { + if i == 0 { + if err := test.init(s); err != nil { + t.Fatalf("test init failed: %s", err) + } + } + if query.skip { + t.Logf("SKIP:: %s", query.name) + continue + } + if err := query.Execute(s); err != nil { + t.Error(query.Error(err)) + } else if !query.success() { + t.Error(query.failureMessage()) + } + } +} + func TestServer_Query_MathWithFill(t *testing.T) { t.Parallel() s := OpenServer(NewConfig()) @@ -4945,18 +5236,24 @@ exp: `{"results":[{"series":[{"name":"cpu","columns":["time","value"],"values":[["2009-11-10T23:00:03Z",2]]}]}]}`, }, &Query{ - name: "where regex all", - params: url.Values{"db": []string{"db0"}}, - command: `select value from cpu where host =~ /.*/`, - exp: `{"results":[{"series":[{"name":"cpu","columns":["time","value"],"values":[["2009-11-10T23:00:02Z",1],["2009-11-10T23:00:03Z",2]]}]}]}`, - }, - &Query{ name: "where regex none", params: url.Values{"db": []string{"db0"}}, command: `select value from cpu where host !~ /.*/`, exp: `{"results":[{}]}`, }, &Query{ + name: "where regex exact", + params: url.Values{"db": []string{"db0"}}, + command: `select value from cpu where host =~ /^server01$/`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","value"],"values":[["2009-11-10T23:00:03Z",2]]}]}]}`, + }, + &Query{ + name: "where regex exact (not)", + params: url.Values{"db": []string{"db0"}}, + command: `select value from cpu where host !~ /^server01$/`, + exp: `{"results":[{"series":[{"name":"cpu","columns":["time","value"],"values":[["2009-11-10T23:00:02Z",1]]}]}]}`, + }, + &Query{ name: "where regex at least one char", params: url.Values{"db": []string{"db0"}}, command: `select value from cpu where host =~ /.+/`, @@ -5608,6 +5905,50 @@ } } +func TestServer_Query_ShowStats(t *testing.T) { + t.Parallel() + s := OpenServer(NewConfig()) + defer s.Close() + + if err := s.CreateDatabaseAndRetentionPolicy("db0", newRetentionPolicySpec("rp0", 1, 0)); err != nil { + t.Fatal(err) + } + if err := s.MetaClient.SetDefaultRetentionPolicy("db0", "rp0"); err != nil { + t.Fatal(err) + } + + if err := s.MetaClient.CreateSubscription("db0", "rp0", "foo", "ALL", []string{"udp://localhost:9000"}); err != nil { + t.Fatal(err) + } + + test := NewTest("db0", "rp0") + test.addQueries([]*Query{ + &Query{ + name: `show shots`, + command: "SHOW STATS", + exp: "subscriber", // Should see a subscriber stat in the json + pattern: true, + }, + }...) + + for i, query := range test.queries { + if i == 0 { + if err := test.init(s); err != nil { + t.Fatalf("test init failed: %s", err) + } + } + if query.skip { + t.Logf("SKIP:: %s", query.name) + continue + } + if err := query.Execute(s); err != nil { + t.Error(query.Error(err)) + } else if !query.success() { + t.Error(query.failureMessage()) + } + } +} + func TestServer_Query_ShowMeasurements(t *testing.T) { t.Parallel() s := OpenServer(NewConfig()) @@ -6004,15 +6345,6 @@ // Run first test to create CQs. runTest(&test, t) - // Trigger CQs to run. - u := fmt.Sprintf("%s/data/process_continuous_queries?time=%d", s.URL(), interval0.UnixNano()) - if _, err := s.HTTPPost(u, nil); err != nil { - t.Fatal(err) - } - - // Wait for CQs to run. TODO: fix this ugly hack - //time.Sleep(time.Second * 5) - // Setup tests to check the CQ results. test2 := NewTest("db0", "rp1") test2.addQueries([]*Query{ @@ -6393,6 +6725,66 @@ } } +// Ensure that binary operators of aggregates of separate fields, when a field is sometimes missing and sometimes present, +// result in values that are still properly time-aligned. +func TestServer_Query_IntoTarget_Sparse(t *testing.T) { + t.Parallel() + s := OpenServer(NewConfig()) + defer s.Close() + + if err := s.CreateDatabaseAndRetentionPolicy("db0", newRetentionPolicySpec("rp0", 1, 0)); err != nil { + t.Fatal(err) + } + if err := s.MetaClient.SetDefaultRetentionPolicy("db0", "rp0"); err != nil { + t.Fatal(err) + } + + writes := []string{ + // All points have fields n and a. Field b is not present in all intervals. + // First 10s interval is missing field b. Result a_n should be (2+5)*(3+7) = 70, b_n is null. + fmt.Sprintf(`foo a=2,n=3 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:01Z").UnixNano()), + fmt.Sprintf(`foo a=5,n=7 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:02Z").UnixNano()), + // Second 10s interval has field b. Result a_n = 11*17 = 187, b_n = 13*17 = 221. + fmt.Sprintf(`foo a=11,b=13,n=17 %d`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:11Z").UnixNano()), + } + + test := NewTest("db0", "rp0") + test.writes = Writes{ + &Write{data: strings.Join(writes, "\n")}, + } + + test.addQueries([]*Query{ + &Query{ + name: "into", + params: url.Values{"db": []string{"db0"}}, + command: `SELECT sum(a) * sum(n) as a_n, sum(b) * sum(n) as b_n INTO baz FROM foo WHERE time >= '2000-01-01T00:00:00Z' AND time < '2000-01-01T00:01:00Z' GROUP BY time(10s)`, + exp: `{"results":[{"series":[{"name":"result","columns":["time","written"],"values":[["1970-01-01T00:00:00Z",2]]}]}]}`, + }, + &Query{ + name: "confirm results", + params: url.Values{"db": []string{"db0"}}, + command: `SELECT * FROM baz`, + exp: `{"results":[{"series":[{"name":"baz","columns":["time","a_n","b_n"],"values":[["2000-01-01T00:00:00Z",70,null],["2000-01-01T00:00:10Z",187,221]]}]}]}`, + }, + }...) + + if err := test.init(s); err != nil { + t.Fatalf("test init failed: %s", err) + } + + for _, query := range test.queries { + if query.skip { + t.Logf("SKIP:: %s", query.name) + continue + } + if err := query.Execute(s); err != nil { + t.Error(query.Error(err)) + } else if !query.success() { + t.Error(query.failureMessage()) + } + } +} + // This test ensures that data is not duplicated with measurements // of the same name. func TestServer_Query_DuplicateMeasurements(t *testing.T) { @@ -6615,6 +7007,64 @@ }, }...) + if err := test.init(s); err != nil { + t.Fatalf("test init failed: %s", err) + } + + for _, query := range test.queries { + if query.skip { + t.Logf("SKIP:: %s", query.name) + continue + } + if err := query.Execute(s); err != nil { + t.Error(query.Error(err)) + } else if !query.success() { + t.Error(query.failureMessage()) + } + } +} + +func TestServer_Query_ImplicitEndTime(t *testing.T) { + t.Skip("flaky test") + t.Parallel() + s := OpenServer(NewConfig()) + defer s.Close() + + if err := s.CreateDatabaseAndRetentionPolicy("db0", newRetentionPolicySpec("rp0", 1, 0)); err != nil { + t.Fatal(err) + } + if err := s.MetaClient.SetDefaultRetentionPolicy("db0", "rp0"); err != nil { + t.Fatal(err) + } + + now := time.Now().UTC().Truncate(time.Second) + past := now.Add(-10 * time.Second) + future := now.Add(10 * time.Minute) + writes := []string{ + fmt.Sprintf(`cpu value=1 %d`, past.UnixNano()), + fmt.Sprintf(`cpu value=2 %d`, future.UnixNano()), + } + + test := NewTest("db0", "rp0") + test.writes = Writes{ + &Write{data: strings.Join(writes, "\n")}, + } + + test.addQueries([]*Query{ + &Query{ + name: "raw query", + params: url.Values{"db": []string{"db0"}}, + command: `SELECT * FROM cpu`, + exp: fmt.Sprintf(`{"results":[{"series":[{"name":"cpu","columns":["time","value"],"values":[["%s",1],["%s",2]]}]}]}`, past.Format(time.RFC3339Nano), future.Format(time.RFC3339Nano)), + }, + &Query{ + name: "aggregate query", + params: url.Values{"db": []string{"db0"}}, + command: `SELECT mean(value) FROM cpu WHERE time > now() - 1m GROUP BY time(1m) FILL(none)`, + exp: fmt.Sprintf(`{"results":[{"series":[{"name":"cpu","columns":["time","mean"],"values":[["%s",1]]}]}]}`, now.Truncate(time.Minute).Format(time.RFC3339Nano)), + }, + }...) + if err := test.init(s); err != nil { t.Fatalf("test init failed: %s", err) } diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/dumptsm/dumptsm.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/dumptsm/dumptsm.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/dumptsm/dumptsm.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/dumptsm/dumptsm.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,334 @@ +package dumptsm + +import ( + "encoding/binary" + "flag" + "fmt" + "io" + "os" + "strconv" + "strings" + "text/tabwriter" + "time" + + "github.com/influxdata/influxdb/tsdb/engine/tsm1" +) + +// Command represents the program execution for "influxd dumptsm". +type Command struct { + // Standard input/output, overridden for testing. + Stderr io.Writer + Stdout io.Writer + + dumpIndex bool + dumpBlocks bool + dumpAll bool + filterKey string + path string +} + +// NewCommand returns a new instance of Command. +func NewCommand() *Command { + return &Command{ + Stderr: os.Stderr, + Stdout: os.Stdout, + } +} + +// Run executes the command. +func (cmd *Command) Run(args ...string) error { + fs := flag.NewFlagSet("file", flag.ExitOnError) + fs.BoolVar(&cmd.dumpIndex, "index", false, "Dump raw index data") + fs.BoolVar(&cmd.dumpBlocks, "blocks", false, "Dump raw block data") + fs.BoolVar(&cmd.dumpAll, "all", false, "Dump all data. Caution: This may print a lot of information") + fs.StringVar(&cmd.filterKey, "filter-key", "", "Only display index and block data match this key substring") + + fs.SetOutput(cmd.Stdout) + fs.Usage = cmd.printUsage + + if err := fs.Parse(args); err != nil { + return err + } + + if fs.Arg(0) == "" { + fmt.Printf("TSM file not specified\n\n") + fs.Usage() + return nil + } + cmd.path = fs.Args()[0] + cmd.dumpBlocks = cmd.dumpBlocks || cmd.dumpAll || cmd.filterKey != "" + cmd.dumpIndex = cmd.dumpIndex || cmd.dumpAll || cmd.filterKey != "" + return cmd.dump() +} + +func (cmd *Command) dump() error { + var errors []error + + f, err := os.Open(cmd.path) + if err != nil { + return err + } + + // Get the file size + stat, err := f.Stat() + if err != nil { + return err + } + b := make([]byte, 8) + + r, err := tsm1.NewTSMReader(f) + if err != nil { + return fmt.Errorf("Error opening TSM files: %s", err.Error()) + } + defer r.Close() + + minTime, maxTime := r.TimeRange() + keyCount := r.KeyCount() + + blockStats := &blockStats{} + + println("Summary:") + fmt.Printf(" File: %s\n", cmd.path) + fmt.Printf(" Time Range: %s - %s\n", + time.Unix(0, minTime).UTC().Format(time.RFC3339Nano), + time.Unix(0, maxTime).UTC().Format(time.RFC3339Nano), + ) + fmt.Printf(" Duration: %s ", time.Unix(0, maxTime).Sub(time.Unix(0, minTime))) + fmt.Printf(" Series: %d ", keyCount) + fmt.Printf(" File Size: %d\n", stat.Size()) + println() + + tw := tabwriter.NewWriter(cmd.Stdout, 8, 8, 1, '\t', 0) + + if cmd.dumpIndex { + println("Index:") + tw.Flush() + println() + + fmt.Fprintln(tw, " "+strings.Join([]string{"Pos", "Min Time", "Max Time", "Ofs", "Size", "Key", "Field"}, "\t")) + var pos int + for i := 0; i < keyCount; i++ { + key, _ := r.KeyAt(i) + for _, e := range r.Entries(string(key)) { + pos++ + split := strings.Split(string(key), "#!~#") + + // We dont' know know if we have fields so use an informative default + var measurement, field string = "UNKNOWN", "UNKNOWN" + + // Possible corruption? Try to read as much as we can and point to the problem. + measurement = split[0] + field = split[1] + + if cmd.filterKey != "" && !strings.Contains(string(key), cmd.filterKey) { + continue + } + fmt.Fprintln(tw, " "+strings.Join([]string{ + strconv.FormatInt(int64(pos), 10), + time.Unix(0, e.MinTime).UTC().Format(time.RFC3339Nano), + time.Unix(0, e.MaxTime).UTC().Format(time.RFC3339Nano), + strconv.FormatInt(int64(e.Offset), 10), + strconv.FormatInt(int64(e.Size), 10), + measurement, + field, + }, "\t")) + tw.Flush() + } + } + } + + tw = tabwriter.NewWriter(cmd.Stdout, 8, 8, 1, '\t', 0) + fmt.Fprintln(tw, " "+strings.Join([]string{"Blk", "Chk", "Ofs", "Len", "Type", "Min Time", "Points", "Enc [T/V]", "Len [T/V]"}, "\t")) + + // Starting at 5 because the magic number is 4 bytes + 1 byte version + i := int64(5) + var blockCount, pointCount, blockSize int64 + indexSize := r.IndexSize() + + // Start at the beginning and read every block + for j := 0; j < keyCount; j++ { + key, _ := r.KeyAt(j) + for _, e := range r.Entries(string(key)) { + + f.Seek(int64(e.Offset), 0) + f.Read(b[:4]) + + chksum := binary.BigEndian.Uint32(b[:4]) + + buf := make([]byte, e.Size-4) + f.Read(buf) + + blockSize += int64(e.Size) + + if cmd.filterKey != "" && !strings.Contains(string(key), cmd.filterKey) { + i += blockSize + blockCount++ + continue + } + + blockType := buf[0] + + encoded := buf[1:] + + var v []tsm1.Value + v, err := tsm1.DecodeBlock(buf, v) + if err != nil { + return err + } + startTime := time.Unix(0, v[0].UnixNano()) + + pointCount += int64(len(v)) + + // Length of the timestamp block + tsLen, j := binary.Uvarint(encoded) + + // Unpack the timestamp bytes + ts := encoded[int(j) : int(j)+int(tsLen)] + + // Unpack the value bytes + values := encoded[int(j)+int(tsLen):] + + tsEncoding := timeEnc[int(ts[0]>>4)] + vEncoding := encDescs[int(blockType+1)][values[0]>>4] + + typeDesc := blockTypes[blockType] + + blockStats.inc(0, ts[0]>>4) + blockStats.inc(int(blockType+1), values[0]>>4) + blockStats.size(len(buf)) + + if cmd.dumpBlocks { + fmt.Fprintln(tw, " "+strings.Join([]string{ + strconv.FormatInt(blockCount, 10), + strconv.FormatUint(uint64(chksum), 10), + strconv.FormatInt(i, 10), + strconv.FormatInt(int64(len(buf)), 10), + typeDesc, + startTime.UTC().Format(time.RFC3339Nano), + strconv.FormatInt(int64(len(v)), 10), + fmt.Sprintf("%s/%s", tsEncoding, vEncoding), + fmt.Sprintf("%d/%d", len(ts), len(values)), + }, "\t")) + } + + i += blockSize + blockCount++ + } + } + + if cmd.dumpBlocks { + println("Blocks:") + tw.Flush() + println() + } + + var blockSizeAvg int64 + if blockCount > 0 { + blockSizeAvg = blockSize / blockCount + } + fmt.Printf("Statistics\n") + fmt.Printf(" Blocks:\n") + fmt.Printf(" Total: %d Size: %d Min: %d Max: %d Avg: %d\n", + blockCount, blockSize, blockStats.min, blockStats.max, blockSizeAvg) + fmt.Printf(" Index:\n") + fmt.Printf(" Total: %d Size: %d\n", blockCount, indexSize) + fmt.Printf(" Points:\n") + fmt.Printf(" Total: %d", pointCount) + println() + + println(" Encoding:") + for i, counts := range blockStats.counts { + if len(counts) == 0 { + continue + } + fmt.Printf(" %s: ", strings.Title(fieldType[i])) + for j, v := range counts { + fmt.Printf("\t%s: %d (%d%%) ", encDescs[i][j], v, int(float64(v)/float64(blockCount)*100)) + } + println() + } + fmt.Printf(" Compression:\n") + fmt.Printf(" Per block: %0.2f bytes/point\n", float64(blockSize)/float64(pointCount)) + fmt.Printf(" Total: %0.2f bytes/point\n", float64(stat.Size())/float64(pointCount)) + + if len(errors) > 0 { + println() + fmt.Printf("Errors (%d):\n", len(errors)) + for _, err := range errors { + fmt.Printf(" * %v\n", err) + } + println() + return fmt.Errorf("error count %d", len(errors)) + } + return nil +} + +// printUsage prints the usage message to STDERR. +func (cmd *Command) printUsage() { + usage := `Dumps low-level details about tsm1 files. + +Usage: influx_inspect dumptsm [flags] + Only display index and block data match this key substring +` + + fmt.Fprintf(cmd.Stdout, usage) +} + +var ( + fieldType = []string{ + "timestamp", "float", "int", "bool", "string", + } + blockTypes = []string{ + "float64", "int64", "bool", "string", + } + timeEnc = []string{ + "none", "s8b", "rle", + } + floatEnc = []string{ + "none", "gor", + } + intEnc = []string{ + "none", "s8b", "rle", + } + boolEnc = []string{ + "none", "bp", + } + stringEnc = []string{ + "none", "snpy", + } + encDescs = [][]string{ + timeEnc, floatEnc, intEnc, boolEnc, stringEnc, + } +) + +type blockStats struct { + min, max int + counts [][]int +} + +func (b *blockStats) inc(typ int, enc byte) { + for len(b.counts) <= typ { + b.counts = append(b.counts, []int{}) + } + for len(b.counts[typ]) <= int(enc) { + b.counts[typ] = append(b.counts[typ], 0) + } + b.counts[typ][enc]++ +} + +func (b *blockStats) size(sz int) { + if b.min == 0 || sz < b.min { + b.min = sz + } + if b.min == 0 || sz > b.max { + b.max = sz + } +} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/dumptsm/dumptsm_test.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/dumptsm/dumptsm_test.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/dumptsm/dumptsm_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/dumptsm/dumptsm_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,3 @@ +package dumptsm_test + +// TODO: write some tests diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/export/export.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/export/export.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/export/export.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/export/export.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,396 @@ +package export + +import ( + "compress/gzip" + "flag" + "fmt" + "io" + "log" + "math" + "os" + "path" + "path/filepath" + "sort" + "strings" + "sync" + "time" + + "github.com/influxdata/influxdb/influxql" + "github.com/influxdata/influxdb/models" + "github.com/influxdata/influxdb/pkg/escape" + "github.com/influxdata/influxdb/tsdb/engine/tsm1" +) + +// Command represents the program execution for "influx_inspect export". +type Command struct { + // Standard input/output, overridden for testing. + Stderr io.Writer + Stdout io.Writer + + dataDir string + walDir string + out string + database string + retentionPolicy string + startTime int64 + endTime int64 + compress bool + + manifest map[string]struct{} + tsmFiles map[string][]string + walFiles map[string][]string +} + +// NewCommand returns a new instance of Command. +func NewCommand() *Command { + return &Command{ + Stderr: os.Stderr, + Stdout: os.Stdout, + + manifest: make(map[string]struct{}), + tsmFiles: make(map[string][]string), + walFiles: make(map[string][]string), + } +} + +// Run executes the command. +func (cmd *Command) Run(args ...string) error { + var start, end string + fs := flag.NewFlagSet("export", flag.ExitOnError) + fs.StringVar(&cmd.dataDir, "datadir", os.Getenv("HOME")+"/.influxdb/data", "Data storage path") + fs.StringVar(&cmd.walDir, "waldir", os.Getenv("HOME")+"/.influxdb/wal", "WAL storage path") + fs.StringVar(&cmd.out, "out", os.Getenv("HOME")+"/.influxdb/export", "Destination file to export to") + fs.StringVar(&cmd.database, "database", "", "Optional: the database to export") + fs.StringVar(&cmd.retentionPolicy, "retention", "", "Optional: the retention policy to export (requires -database)") + fs.StringVar(&start, "start", "", "Optional: the start time to export") + fs.StringVar(&end, "end", "", "Optional: the end time to export") + fs.BoolVar(&cmd.compress, "compress", false, "Compress the output") + + fs.SetOutput(cmd.Stdout) + fs.Usage = func() { + fmt.Fprintf(cmd.Stdout, "Exports TSM files into InfluxDB line protocol format.\n\n") + fmt.Fprintf(cmd.Stdout, "Usage: %s export [flags]\n\n", filepath.Base(os.Args[0])) + fs.PrintDefaults() + } + + if err := fs.Parse(args); err != nil { + return err + } + + // set defaults + if start != "" { + s, err := time.Parse(time.RFC3339, start) + if err != nil { + return err + } + cmd.startTime = s.UnixNano() + } else { + cmd.startTime = math.MinInt64 + } + if end != "" { + e, err := time.Parse(time.RFC3339, end) + if err != nil { + return err + } + cmd.endTime = e.UnixNano() + } else { + // set end time to max if it is not set. + cmd.endTime = math.MaxInt64 + } + + if err := cmd.validate(); err != nil { + return err + } + + return cmd.export() +} + +func (cmd *Command) validate() error { + // validate args + if cmd.retentionPolicy != "" && cmd.database == "" { + return fmt.Errorf("must specify a db") + } + if cmd.startTime != 0 && cmd.endTime != 0 && cmd.endTime < cmd.startTime { + return fmt.Errorf("end time before start time") + } + return nil +} + +func (cmd *Command) export() error { + if err := cmd.walkTSMFiles(); err != nil { + return err + } + if err := cmd.walkWALFiles(); err != nil { + return err + } + return cmd.writeFiles() +} + +func (cmd *Command) walkTSMFiles() error { + err := filepath.Walk(cmd.dataDir, func(dir string, f os.FileInfo, err error) error { + if err != nil { + return err + } + + // check to see if this is a tsm file + ext := fmt.Sprintf(".%s", tsm1.TSMFileExtension) + if filepath.Ext(dir) != ext { + return nil + } + + relPath, _ := filepath.Rel(cmd.dataDir, dir) + dirs := strings.Split(relPath, string(byte(os.PathSeparator))) + if len(dirs) < 2 { + return fmt.Errorf("invalid directory structure for %s", dir) + } + if dirs[0] == cmd.database || cmd.database == "" { + if dirs[1] == cmd.retentionPolicy || cmd.retentionPolicy == "" { + key := filepath.Join(dirs[0], dirs[1]) + files := cmd.tsmFiles[key] + if files == nil { + files = []string{} + } + cmd.manifest[key] = struct{}{} + cmd.tsmFiles[key] = append(files, dir) + } + } + return nil + }) + if err != nil { + return err + } + return nil +} + +func (cmd *Command) walkWALFiles() error { + err := filepath.Walk(cmd.walDir, func(dir string, f os.FileInfo, err error) error { + if err != nil { + return err + } + + // check to see if this is a wal file + prefix := tsm1.WALFilePrefix + ext := fmt.Sprintf(".%s", tsm1.WALFileExtension) + _, fileName := path.Split(dir) + if filepath.Ext(dir) != ext || !strings.HasPrefix(fileName, prefix) { + return nil + } + + relPath, _ := filepath.Rel(cmd.walDir, dir) + dirs := strings.Split(relPath, string(byte(os.PathSeparator))) + if len(dirs) < 2 { + return fmt.Errorf("invalid directory structure for %s", dir) + } + if dirs[0] == cmd.database || cmd.database == "" { + if dirs[1] == cmd.retentionPolicy || cmd.retentionPolicy == "" { + key := filepath.Join(dirs[0], dirs[1]) + files := cmd.walFiles[key] + if files == nil { + files = []string{} + } + cmd.manifest[key] = struct{}{} + cmd.walFiles[key] = append(files, dir) + } + } + return nil + }) + if err != nil { + return err + } + return nil +} + +func (cmd *Command) writeFiles() error { + // open our output file and create an output buffer + var w io.WriteCloser + w, err := os.Create(cmd.out) + if err != nil { + return err + } + defer w.Close() + if cmd.compress { + w = gzip.NewWriter(w) + defer w.Close() + } + + s, e := time.Unix(0, cmd.startTime).Format(time.RFC3339), time.Unix(0, cmd.endTime).Format(time.RFC3339) + fmt.Fprintf(w, "# INFLUXDB EXPORT: %s - %s\n", s, e) + + // Write out all the DDL + fmt.Fprintln(w, "# DDL") + for key := range cmd.manifest { + keys := strings.Split(key, string(byte(os.PathSeparator))) + db, rp := influxql.QuoteIdent(keys[0]), influxql.QuoteIdent(keys[1]) + fmt.Fprintf(w, "CREATE DATABASE %s WITH NAME %s\n", db, rp) + } + + fmt.Fprintln(w, "# DML") + for key := range cmd.manifest { + keys := strings.Split(key, string(byte(os.PathSeparator))) + fmt.Fprintf(w, "# CONTEXT-DATABASE:%s\n", keys[0]) + fmt.Fprintf(w, "# CONTEXT-RETENTION-POLICY:%s\n", keys[1]) + if files, ok := cmd.tsmFiles[key]; ok { + fmt.Printf("writing out tsm file data for %s...", key) + if err := cmd.writeTsmFiles(w, files); err != nil { + return err + } + fmt.Println("complete.") + } + if _, ok := cmd.walFiles[key]; ok { + fmt.Printf("writing out wal file data for %s...", key) + if err := cmd.writeWALFiles(w, cmd.walFiles[key], key); err != nil { + return err + } + fmt.Println("complete.") + } + } + return nil +} + +func (cmd *Command) writeTsmFiles(w io.WriteCloser, files []string) error { + fmt.Fprintln(w, "# writing tsm data") + + // we need to make sure we write the same order that the files were written + sort.Strings(files) + + // use a function here to close the files in the defers and not let them accumulate in the loop + write := func(f string) error { + file, err := os.OpenFile(f, os.O_RDONLY, 0600) + if err != nil { + return fmt.Errorf("%v", err) + } + defer file.Close() + reader, err := tsm1.NewTSMReader(file) + if err != nil { + log.Printf("unable to read %s, skipping\n", f) + return nil + } + defer reader.Close() + + if sgStart, sgEnd := reader.TimeRange(); sgStart > cmd.endTime || sgEnd < cmd.startTime { + return nil + } + + for i := 0; i < reader.KeyCount(); i++ { + var pairs string + key, typ := reader.KeyAt(i) + values, _ := reader.ReadAll(string(key)) + measurement, field := tsm1.SeriesAndFieldFromCompositeKey(key) + // measurements are stored escaped, field names are not + field = escape.String(field) + + for _, value := range values { + if (value.UnixNano() < cmd.startTime) || (value.UnixNano() > cmd.endTime) { + continue + } + + switch typ { + case tsm1.BlockFloat64: + pairs = field + "=" + fmt.Sprintf("%v", value.Value()) + case tsm1.BlockInteger: + pairs = field + "=" + fmt.Sprintf("%vi", value.Value()) + case tsm1.BlockBoolean: + pairs = field + "=" + fmt.Sprintf("%v", value.Value()) + case tsm1.BlockString: + pairs = field + "=" + fmt.Sprintf("%q", models.EscapeStringField(fmt.Sprintf("%s", value.Value()))) + default: + pairs = field + "=" + fmt.Sprintf("%v", value.Value()) + } + + fmt.Fprintln(w, string(measurement), pairs, value.UnixNano()) + } + } + return nil + } + + for _, f := range files { + if err := write(f); err != nil { + return err + } + } + + return nil +} + +func (cmd *Command) writeWALFiles(w io.WriteCloser, files []string, key string) error { + fmt.Fprintln(w, "# writing wal data") + + // we need to make sure we write the same order that the wal received the data + sort.Strings(files) + + var once sync.Once + warn := func() { + msg := fmt.Sprintf(`WARNING: detected deletes in wal file. + Some series for %q may be brought back by replaying this data. + To resolve, you can either let the shard snapshot prior to exporting the data + or manually editing the exported file. + `, key) + fmt.Fprintln(cmd.Stderr, msg) + } + + // use a function here to close the files in the defers and not let them accumulate in the loop + write := func(f string) error { + file, err := os.OpenFile(f, os.O_RDONLY, 0600) + if err != nil { + return fmt.Errorf("%v", err) + } + defer file.Close() + + reader := tsm1.NewWALSegmentReader(file) + defer reader.Close() + for reader.Next() { + entry, err := reader.Read() + if err != nil { + n := reader.Count() + fmt.Fprintf(os.Stderr, "file %s corrupt at position %d", file.Name(), n) + break + } + + switch t := entry.(type) { + case *tsm1.DeleteWALEntry: + once.Do(warn) + continue + case *tsm1.DeleteRangeWALEntry: + once.Do(warn) + continue + case *tsm1.WriteWALEntry: + var pairs string + + for key, values := range t.Values { + measurement, field := tsm1.SeriesAndFieldFromCompositeKey([]byte(key)) + // measurements are stored escaped, field names are not + field = escape.String(field) + + for _, value := range values { + if (value.UnixNano() < cmd.startTime) || (value.UnixNano() > cmd.endTime) { + continue + } + + switch value.Value().(type) { + case float64: + pairs = field + "=" + fmt.Sprintf("%v", value.Value()) + case int64: + pairs = field + "=" + fmt.Sprintf("%vi", value.Value()) + case bool: + pairs = field + "=" + fmt.Sprintf("%v", value.Value()) + case string: + pairs = field + "=" + fmt.Sprintf("%q", models.EscapeStringField(fmt.Sprintf("%s", value.Value()))) + default: + pairs = field + "=" + fmt.Sprintf("%v", value.Value()) + } + fmt.Fprintln(w, string(measurement), pairs, value.UnixNano()) + } + } + } + } + return nil + } + + for _, f := range files { + if err := write(f); err != nil { + return err + } + } + + return nil +} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/export/export_test.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/export/export_test.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/export/export_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/export/export_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,3 @@ +package export_test + +// #TODO: write some tests diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/export.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/export.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/export.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/export.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -package main - -import ( - "compress/gzip" - "fmt" - "io" - "log" - "os" - "path/filepath" - "strings" - - "github.com/influxdata/influxdb/models" - "github.com/influxdata/influxdb/tsdb/engine/tsm1" -) - -type cmdExport struct { - path string - out string - db string - retentionPolicy string - compress bool - - ext string - files map[string][]string -} - -func newCmdExport(path, out, db, retentionPolicy string, compress bool) *cmdExport { - return &cmdExport{ - path: filepath.Join(path, "data"), - out: out, - db: db, - compress: compress, - ext: fmt.Sprintf(".%s", tsm1.TSMFileExtension), - retentionPolicy: retentionPolicy, - files: make(map[string][]string), - } -} - -func (c *cmdExport) validate() error { - // validate args - if c.retentionPolicy != "" && c.db == "" { - return fmt.Errorf("must specify a db") - } - return nil -} - -func (c *cmdExport) run() error { - if err := c.validate(); err != nil { - return err - } - - return c.export() -} - -func (c *cmdExport) export() error { - if err := c.walkFiles(); err != nil { - return err - } - return c.writeFiles() -} - -func (c *cmdExport) walkFiles() error { - err := filepath.Walk(c.path, func(path string, f os.FileInfo, err error) error { - if err != nil { - return err - } - if filepath.Ext(path) == c.ext { - //files = append(files, path) - relPath, _ := filepath.Rel(c.path, path) - dirs := strings.Split(relPath, string(byte(os.PathSeparator))) - if dirs[0] == c.db || c.db == "" { - if dirs[1] == c.retentionPolicy || c.retentionPolicy == "" { - key := filepath.Join(dirs[0], dirs[1]) - files := c.files[key] - if files == nil { - files = []string{} - } - c.files[key] = append(files, path) - } - } - } - return nil - }) - if err != nil { - log.Fatal(err) - } - return nil -} - -func (c *cmdExport) writeFiles() error { - // open our output file and create an output buffer - var w io.WriteCloser - w, err := os.Create(c.out) - if err != nil { - return err - } - defer w.Close() - if c.compress { - w = gzip.NewWriter(w) - defer w.Close() - } - - // Write out all the DDL - fmt.Fprintln(w, "# DDL") - for key, _ := range c.files { - keys := strings.Split(key, string(byte(os.PathSeparator))) - fmt.Fprintf(w, "CREATE DATABASE %s\n", keys[0]) - fmt.Fprintf(w, "CREATE RETENTION POLICY %s ON %s DURATION inf REPLICATION 1\n", keys[1], keys[0]) - } - - fmt.Fprintln(w, "# DML") - for key, files := range c.files { - keys := strings.Split(key, string(byte(os.PathSeparator))) - fmt.Fprintf(w, "# CONTEXT-DATABASE:%s\n", keys[0]) - fmt.Fprintf(w, "# CONTEXT-RETENTION-POLICY:%s\n", keys[1]) - for _, f := range files { - // use an anonymous function here to close the files in the defers and not let them - // accumulate in the loop - if err := func(f string) error { - file, err := os.OpenFile(f, os.O_RDONLY, 0600) - if err != nil { - return fmt.Errorf("%v", err) - } - defer file.Close() - reader, err := tsm1.NewTSMReader(file) - if err != nil { - log.Printf("unable to read %s, skipping\n", f) - return nil - } - defer reader.Close() - - for i := 0; i < reader.KeyCount(); i++ { - var pairs string - key, typ := reader.KeyAt(i) - values, _ := reader.ReadAll(key) - measurement, field := tsm1.SeriesAndFieldFromCompositeKey(key) - - for _, value := range values { - switch typ { - case tsm1.BlockFloat64: - pairs = field + "=" + fmt.Sprintf("%v", value.Value()) - case tsm1.BlockInteger: - pairs = field + "=" + fmt.Sprintf("%vi", value.Value()) - case tsm1.BlockBoolean: - pairs = field + "=" + fmt.Sprintf("%v", value.Value()) - case tsm1.BlockString: - pairs = field + "=" + fmt.Sprintf("%q", models.EscapeStringField(fmt.Sprintf("%s", value.Value()))) - default: - pairs = field + "=" + fmt.Sprintf("%v", value.Value()) - } - - fmt.Fprintln(w, measurement, pairs, value.UnixNano()) - } - } - return nil - }(f); err != nil { - return err - } - } - _ = key - } - return nil -} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/help/help.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/help/help.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/help/help.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/help/help.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,41 @@ +package help + +import ( + "fmt" + "io" + "os" + "strings" +) + +// Command displays help for command-line sub-commands. +type Command struct { + Stdout io.Writer +} + +// NewCommand returns a new instance of Command. +func NewCommand() *Command { + return &Command{ + Stdout: os.Stdout, + } +} + +// Run executes the command. +func (cmd *Command) Run(args ...string) error { + fmt.Fprintln(cmd.Stdout, strings.TrimSpace(usage)) + return nil +} + +const usage = ` +Usage: influx_inspect [[command] [arguments]] + +The commands are: + + dumptsm dumps low-level details about tsm1 files. + export exports raw data from a shard to line protocol + help display this help message + report displays a shard level report + +"help" is the default command. + +Use "influx_inspect [command] -help" for more information about a command. +` diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/help/help_test.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/help/help_test.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/help/help_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/help/help_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,3 @@ +package help_test + +// TODO: write some tests diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/main.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/main.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/main.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/main.go 2016-12-06 21:36:15.000000000 +0000 @@ -1,136 +1,84 @@ package main import ( - "flag" "fmt" + "io" + "log" "os" + "github.com/influxdata/influxdb/cmd" + "github.com/influxdata/influxdb/cmd/influx_inspect/dumptsm" + "github.com/influxdata/influxdb/cmd/influx_inspect/export" + "github.com/influxdata/influxdb/cmd/influx_inspect/help" + "github.com/influxdata/influxdb/cmd/influx_inspect/report" + "github.com/influxdata/influxdb/cmd/influx_inspect/verify" _ "github.com/influxdata/influxdb/tsdb/engine" ) -func usage() { - println(`Usage: influx_inspect [options] - -Displays detailed information about InfluxDB data files. -`) +func main() { - println(`Commands: - dumptsm - dumps low-level details about tsm1 files. - export - exports a tsm file to line protocol - report - displays a shard level report`) - println() + m := NewMain() + if err := m.Run(os.Args[1:]...); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } -func main() { - - flag.Usage = usage - flag.Parse() +// Main represents the program execution. +type Main struct { + Logger *log.Logger + + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} - if len(flag.Args()) == 0 { - flag.Usage() - os.Exit(0) +// NewMain return a new instance of Main. +func NewMain() *Main { + return &Main{ + Logger: log.New(os.Stderr, "[influx_inspect] ", log.LstdFlags), + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, } +} - switch flag.Args()[0] { - case "report": - opts := &reportOpts{} - fs := flag.NewFlagSet("report", flag.ExitOnError) - fs.StringVar(&opts.pattern, "pattern", "", "Include only files matching a pattern") - fs.BoolVar(&opts.detailed, "detailed", false, "Report detailed cardinality estimates") - - fs.Usage = func() { - println("Usage: influx_inspect report [options]\n\n Displays shard level report") - println() - println("Options:") - fs.PrintDefaults() - } - - if err := fs.Parse(flag.Args()[1:]); err != nil { - fmt.Printf("%v", err) - os.Exit(1) +// Run determines and runs the command specified by the CLI args. +func (m *Main) Run(args ...string) error { + name, args := cmd.ParseCommandName(args) + + // Extract name from args. + switch name { + case "", "help": + if err := help.NewCommand().Run(args...); err != nil { + return fmt.Errorf("help: %s", err) } - opts.dir = fs.Arg(0) - cmdReport(opts) case "dumptsmdev": - fmt.Fprintf(os.Stderr, "warning: dumptsmdev is deprecated, use dumptsm instead.\n") + fmt.Fprintf(m.Stderr, "warning: dumptsmdev is deprecated, use dumptsm instead.\n") fallthrough case "dumptsm": - var dumpAll bool - opts := &tsdmDumpOpts{} - fs := flag.NewFlagSet("file", flag.ExitOnError) - fs.BoolVar(&opts.dumpIndex, "index", false, "Dump raw index data") - fs.BoolVar(&opts.dumpBlocks, "blocks", false, "Dump raw block data") - fs.BoolVar(&dumpAll, "all", false, "Dump all data. Caution: This may print a lot of information") - fs.StringVar(&opts.filterKey, "filter-key", "", "Only display index and block data match this key substring") - - fs.Usage = func() { - println("Usage: influx_inspect dumptsm [options] \n\n Dumps low-level details about tsm1 files.") - println() - println("Options:") - fs.PrintDefaults() - os.Exit(0) - } - - if err := fs.Parse(flag.Args()[1:]); err != nil { - fmt.Printf("%v", err) - os.Exit(1) - } - - if len(fs.Args()) == 0 || fs.Args()[0] == "" { - fmt.Printf("TSM file not specified\n\n") - fs.Usage() - fs.PrintDefaults() - os.Exit(1) - } - opts.path = fs.Args()[0] - opts.dumpBlocks = opts.dumpBlocks || dumpAll || opts.filterKey != "" - opts.dumpIndex = opts.dumpIndex || dumpAll || opts.filterKey != "" - cmdDumpTsm1(opts) - case "verify": - var path string - fs := flag.NewFlagSet("verify", flag.ExitOnError) - fs.StringVar(&path, "dir", os.Getenv("HOME")+"/.influxdb", "Root storage path. [$HOME/.influxdb]") - - fs.Usage = func() { - println("Usage: influx_inspect verify [options]\n\n verifies the the checksum of shards") - println() - println("Options:") - fs.PrintDefaults() - } - - if err := fs.Parse(flag.Args()[1:]); err != nil { - fmt.Printf("%v", err) - os.Exit(1) + name := dumptsm.NewCommand() + if err := name.Run(args...); err != nil { + return fmt.Errorf("dumptsm: %s", err) } - cmdVerify(path) case "export": - var path, out, db, rp string - var compress bool - fs := flag.NewFlagSet("export", flag.ExitOnError) - fs.StringVar(&path, "dir", os.Getenv("HOME")+"/.influxdb", "Root storage path. [$HOME/.influxdb]") - fs.StringVar(&out, "out", os.Getenv("HOME")+"/.influxdb/export", "Destination file to export to") - fs.StringVar(&db, "db", "", "Optional: the database to export") - fs.StringVar(&rp, "rp", "", "Optional: the retention policy to export (requires db parameter to be specified)") - fs.BoolVar(&compress, "compress", false, "Compress the output") - - fs.Usage = func() { - println("Usage: influx_inspect export [options]\n\n exports TSM files into InfluxDB line protocol format") - println() - println("Options:") - fs.PrintDefaults() + name := export.NewCommand() + if err := name.Run(args...); err != nil { + return fmt.Errorf("export: %s", err) } - - if err := fs.Parse(flag.Args()[1:]); err != nil { - fmt.Printf("%v", err) - os.Exit(1) + case "report": + name := report.NewCommand() + if err := name.Run(args...); err != nil { + return fmt.Errorf("report: %s", err) } - c := newCmdExport(path, out, db, rp, compress) - if err := c.run(); err != nil { - fmt.Println(err) - os.Exit(1) + case "verify": + name := verify.NewCommand() + if err := name.Run(args...); err != nil { + return fmt.Errorf("verify: %s", err) } default: - flag.Usage() - os.Exit(1) + return fmt.Errorf(`unknown command "%s"`+"\n"+`Run 'influx_inspect help' for usage`+"\n\n", name) } + + return nil } diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/README.md influxdb-1.1.1+dfsg1/cmd/influx_inspect/README.md --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/README.md 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/README.md 2016-12-06 21:36:15.000000000 +0000 @@ -38,26 +38,37 @@ Exports all tsm files to line protocol. This output file can be imported via the [influx](https://github.com/influxdata/influxdb/tree/master/importer#running-the-import-command) command. -#### `-dir` string -Root storage path. +#### `-datadir` string +Data storage path. -`default` = "$HOME/.influxdb" +`default` = "$HOME/.influxdb/data" + +#### `-waldir` string +WAL storage path. + +`default` = "$HOME/.influxdb/wal" #### `-out` string Destination file to export to `default` = "$HOME/.influxdb/export" -#### `-db` string (optional) +#### `-database` string (optional) Database to export. `default` = "" -#### `-rp` string (optional) +#### `-retention` string (optional) Retention policy to export. `default` = "" +#### `-start` string (optional) +Optional. The time range to start at. + +#### `-end` string (optional) +Optional. The time range to end at. + #### `-compress` bool (optional) Compress the output. diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/report/report.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/report/report.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/report/report.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/report/report.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,184 @@ +package report + +import ( + "flag" + "fmt" + "io" + "os" + "path/filepath" + "strconv" + "strings" + "text/tabwriter" + "time" + + "github.com/influxdata/influxdb/models" + "github.com/influxdata/influxdb/tsdb/engine/tsm1" + "github.com/retailnext/hllpp" +) + +// Command represents the program execution for "influxd report". +type Command struct { + Stderr io.Writer + Stdout io.Writer + + dir string + pattern string + detailed bool +} + +// NewCommand returns a new instance of Command. +func NewCommand() *Command { + return &Command{ + Stderr: os.Stderr, + Stdout: os.Stdout, + } +} + +// Run executes the command. +func (cmd *Command) Run(args ...string) error { + fs := flag.NewFlagSet("report", flag.ExitOnError) + fs.StringVar(&cmd.pattern, "pattern", "", "Include only files matching a pattern") + fs.BoolVar(&cmd.detailed, "detailed", false, "Report detailed cardinality estimates") + + fs.SetOutput(cmd.Stdout) + fs.Usage = cmd.printUsage + + if err := fs.Parse(args); err != nil { + return err + } + cmd.dir = fs.Arg(0) + + start := time.Now() + + files, err := filepath.Glob(filepath.Join(cmd.dir, fmt.Sprintf("*.%s", tsm1.TSMFileExtension))) + if err != nil { + return err + } + + var filtered []string + if cmd.pattern != "" { + for _, f := range files { + if strings.Contains(f, cmd.pattern) { + filtered = append(filtered, f) + } + } + files = filtered + } + + if len(files) == 0 { + return fmt.Errorf("no tsm files at %v\n", cmd.dir) + } + + tw := tabwriter.NewWriter(cmd.Stdout, 8, 8, 1, '\t', 0) + fmt.Fprintln(tw, strings.Join([]string{"File", "Series", "Load Time"}, "\t")) + + totalSeries := hllpp.New() + tagCardialities := map[string]*hllpp.HLLPP{} + measCardinalities := map[string]*hllpp.HLLPP{} + fieldCardinalities := map[string]*hllpp.HLLPP{} + + ordering := make([]chan struct{}, 0, len(files)) + for range files { + ordering = append(ordering, make(chan struct{})) + } + + for _, f := range files { + file, err := os.OpenFile(f, os.O_RDONLY, 0600) + if err != nil { + fmt.Fprintf(cmd.Stderr, "error: %s: %v. Skipping.\n", f, err) + continue + } + + loadStart := time.Now() + reader, err := tsm1.NewTSMReader(file) + if err != nil { + fmt.Fprintf(cmd.Stderr, "error: %s: %v. Skipping.\n", file.Name(), err) + continue + } + loadTime := time.Since(loadStart) + + seriesCount := reader.KeyCount() + for i := 0; i < seriesCount; i++ { + key, _ := reader.KeyAt(i) + totalSeries.Add([]byte(key)) + + if cmd.detailed { + sep := strings.Index(string(key), "#!~#") + seriesKey, field := key[:sep], key[sep+4:] + measurement, tags, _ := models.ParseKey(seriesKey) + + measCount, ok := measCardinalities[measurement] + if !ok { + measCount = hllpp.New() + measCardinalities[measurement] = measCount + } + measCount.Add([]byte(key)) + + fieldCount, ok := fieldCardinalities[measurement] + if !ok { + fieldCount = hllpp.New() + fieldCardinalities[measurement] = fieldCount + } + fieldCount.Add([]byte(field)) + + for _, t := range tags { + tagCount, ok := tagCardialities[string(t.Key)] + if !ok { + tagCount = hllpp.New() + tagCardialities[string(t.Key)] = tagCount + } + tagCount.Add(t.Value) + } + } + } + reader.Close() + + fmt.Fprintln(tw, strings.Join([]string{ + filepath.Base(file.Name()), + strconv.FormatInt(int64(seriesCount), 10), + loadTime.String(), + }, "\t")) + tw.Flush() + } + + tw.Flush() + println() + fmt.Printf("Statistics\n") + fmt.Printf(" Series:\n") + fmt.Printf(" Total (est): %d\n", totalSeries.Count()) + if cmd.detailed { + fmt.Printf(" Measurements (est):\n") + for t, card := range measCardinalities { + fmt.Printf(" %v: %d (%d%%)\n", t, card.Count(), int((float64(card.Count())/float64(totalSeries.Count()))*100)) + } + + fmt.Printf(" Fields (est):\n") + for t, card := range fieldCardinalities { + fmt.Printf(" %v: %d\n", t, card.Count()) + } + + fmt.Printf(" Tags (est):\n") + for t, card := range tagCardialities { + fmt.Printf(" %v: %d\n", t, card.Count()) + } + } + + fmt.Printf("Completed in %s\n", time.Since(start)) + return nil +} + +// printUsage prints the usage message to STDERR. +func (cmd *Command) printUsage() { + usage := `Displays shard level report. + +Usage: influx_inspect report [flags] + + -pattern + Include only files matching a pattern. + -detailed + Report detailed cardinality estimates. + Defaults to "false". +` + + fmt.Fprintf(cmd.Stdout, usage) +} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/report/report_test.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/report/report_test.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/report/report_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/report/report_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,3 @@ +package report_test + +// TODO: write some tests diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/report.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/report.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/report.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/report.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,142 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - "text/tabwriter" - "time" - - "github.com/influxdata/influxdb/models" - "github.com/influxdata/influxdb/tsdb/engine/tsm1" - "github.com/retailnext/hllpp" -) - -type reportOpts struct { - dir string - pattern string - detailed bool -} - -func cmdReport(opts *reportOpts) { - start := time.Now() - - files, err := filepath.Glob(filepath.Join(opts.dir, fmt.Sprintf("*.%s", tsm1.TSMFileExtension))) - if err != nil { - fmt.Printf("%v\n", err) - os.Exit(1) - } - - var filtered []string - if opts.pattern != "" { - for _, f := range files { - if strings.Contains(f, opts.pattern) { - filtered = append(filtered, f) - } - } - files = filtered - } - - if len(files) == 0 { - fmt.Printf("no tsm files at %v\n", opts.dir) - os.Exit(1) - } - - tw := tabwriter.NewWriter(os.Stdout, 8, 8, 1, '\t', 0) - fmt.Fprintln(tw, strings.Join([]string{"File", "Series", "Load Time"}, "\t")) - - totalSeries := hllpp.New() - tagCardialities := map[string]*hllpp.HLLPP{} - measCardinalities := map[string]*hllpp.HLLPP{} - fieldCardinalities := map[string]*hllpp.HLLPP{} - - ordering := make([]chan struct{}, 0, len(files)) - for range files { - ordering = append(ordering, make(chan struct{})) - } - - for _, f := range files { - file, err := os.OpenFile(f, os.O_RDONLY, 0600) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %s: %v. Skipping.\n", f, err) - continue - } - - loadStart := time.Now() - reader, err := tsm1.NewTSMReader(file) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %s: %v. Skipping.\n", file.Name(), err) - continue - } - loadTime := time.Since(loadStart) - - seriesCount := reader.KeyCount() - for i := 0; i < seriesCount; i++ { - key, _ := reader.KeyAt(i) - totalSeries.Add([]byte(key)) - - if opts.detailed { - sep := strings.Index(key, "#!~#") - seriesKey, field := key[:sep], key[sep+4:] - measurement, tags, _ := models.ParseKey(seriesKey) - - measCount, ok := measCardinalities[measurement] - if !ok { - measCount = hllpp.New() - measCardinalities[measurement] = measCount - } - measCount.Add([]byte(key)) - - fieldCount, ok := fieldCardinalities[measurement] - if !ok { - fieldCount = hllpp.New() - fieldCardinalities[measurement] = fieldCount - } - fieldCount.Add([]byte(field)) - - for t, v := range tags { - tagCount, ok := tagCardialities[t] - if !ok { - tagCount = hllpp.New() - tagCardialities[t] = tagCount - } - tagCount.Add([]byte(v)) - } - } - } - reader.Close() - - fmt.Fprintln(tw, strings.Join([]string{ - filepath.Base(file.Name()), - strconv.FormatInt(int64(seriesCount), 10), - loadTime.String(), - }, "\t")) - tw.Flush() - } - - tw.Flush() - println() - fmt.Printf("Statistics\n") - fmt.Printf(" Series:\n") - fmt.Printf(" Total (est): %d\n", totalSeries.Count()) - if opts.detailed { - fmt.Printf(" Measurements (est):\n") - for t, card := range measCardinalities { - fmt.Printf(" %v: %d (%d%%)\n", t, card.Count(), int((float64(card.Count())/float64(totalSeries.Count()))*100)) - } - - fmt.Printf(" Fields (est):\n") - for t, card := range fieldCardinalities { - fmt.Printf(" %v: %d\n", t, card.Count()) - } - - fmt.Printf(" Tags (est):\n") - for t, card := range tagCardialities { - fmt.Printf(" %v: %d\n", t, card.Count()) - } - } - - fmt.Printf("Completed in %s\n", time.Since(start)) -} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/tsm.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/tsm.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/tsm.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/tsm.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,275 +0,0 @@ -package main - -import ( - "encoding/binary" - "fmt" - "os" - "strconv" - "strings" - "text/tabwriter" - "time" - - "github.com/influxdata/influxdb/tsdb/engine/tsm1" -) - -type tsdmDumpOpts struct { - dumpIndex bool - dumpBlocks bool - filterKey string - path string -} - -type blockStats struct { - min, max int - counts [][]int -} - -func (b *blockStats) inc(typ int, enc byte) { - for len(b.counts) <= typ { - b.counts = append(b.counts, []int{}) - } - for len(b.counts[typ]) <= int(enc) { - b.counts[typ] = append(b.counts[typ], 0) - } - b.counts[typ][enc]++ -} - -func (b *blockStats) size(sz int) { - if b.min == 0 || sz < b.min { - b.min = sz - } - if b.min == 0 || sz > b.max { - b.max = sz - } -} - -var ( - fieldType = []string{ - "timestamp", "float", "int", "bool", "string", - } - blockTypes = []string{ - "float64", "int64", "bool", "string", - } - timeEnc = []string{ - "none", "s8b", "rle", - } - floatEnc = []string{ - "none", "gor", - } - intEnc = []string{ - "none", "s8b", "rle", - } - boolEnc = []string{ - "none", "bp", - } - stringEnc = []string{ - "none", "snpy", - } - encDescs = [][]string{ - timeEnc, floatEnc, intEnc, boolEnc, stringEnc, - } -) - -func cmdDumpTsm1(opts *tsdmDumpOpts) { - var errors []error - - f, err := os.Open(opts.path) - if err != nil { - println(err.Error()) - os.Exit(1) - } - - // Get the file size - stat, err := f.Stat() - if err != nil { - println(err.Error()) - os.Exit(1) - } - b := make([]byte, 8) - - r, err := tsm1.NewTSMReader(f) - if err != nil { - println("Error opening TSM files: ", err.Error()) - os.Exit(1) - } - defer r.Close() - - minTime, maxTime := r.TimeRange() - keyCount := r.KeyCount() - - blockStats := &blockStats{} - - println("Summary:") - fmt.Printf(" File: %s\n", opts.path) - fmt.Printf(" Time Range: %s - %s\n", - time.Unix(0, minTime).UTC().Format(time.RFC3339Nano), - time.Unix(0, maxTime).UTC().Format(time.RFC3339Nano), - ) - fmt.Printf(" Duration: %s ", time.Unix(0, maxTime).Sub(time.Unix(0, minTime))) - fmt.Printf(" Series: %d ", keyCount) - fmt.Printf(" File Size: %d\n", stat.Size()) - println() - - tw := tabwriter.NewWriter(os.Stdout, 8, 8, 1, '\t', 0) - - if opts.dumpIndex { - println("Index:") - tw.Flush() - println() - - fmt.Fprintln(tw, " "+strings.Join([]string{"Pos", "Min Time", "Max Time", "Ofs", "Size", "Key", "Field"}, "\t")) - var pos int - for i := 0; i < keyCount; i++ { - key, _ := r.KeyAt(i) - for _, e := range r.Entries(key) { - pos++ - split := strings.Split(key, "#!~#") - - // We dont' know know if we have fields so use an informative default - var measurement, field string = "UNKNOWN", "UNKNOWN" - - // Possible corruption? Try to read as much as we can and point to the problem. - measurement = split[0] - field = split[1] - - if opts.filterKey != "" && !strings.Contains(key, opts.filterKey) { - continue - } - fmt.Fprintln(tw, " "+strings.Join([]string{ - strconv.FormatInt(int64(pos), 10), - time.Unix(0, e.MinTime).UTC().Format(time.RFC3339Nano), - time.Unix(0, e.MaxTime).UTC().Format(time.RFC3339Nano), - strconv.FormatInt(int64(e.Offset), 10), - strconv.FormatInt(int64(e.Size), 10), - measurement, - field, - }, "\t")) - tw.Flush() - } - } - } - - tw = tabwriter.NewWriter(os.Stdout, 8, 8, 1, '\t', 0) - fmt.Fprintln(tw, " "+strings.Join([]string{"Blk", "Chk", "Ofs", "Len", "Type", "Min Time", "Points", "Enc [T/V]", "Len [T/V]"}, "\t")) - - // Starting at 5 because the magic number is 4 bytes + 1 byte version - i := int64(5) - var blockCount, pointCount, blockSize int64 - indexSize := r.IndexSize() - - // Start at the beginning and read every block - for j := 0; j < keyCount; j++ { - key, _ := r.KeyAt(j) - for _, e := range r.Entries(key) { - - f.Seek(int64(e.Offset), 0) - f.Read(b[:4]) - - chksum := binary.BigEndian.Uint32(b[:4]) - - buf := make([]byte, e.Size-4) - f.Read(buf) - - blockSize += int64(e.Size) - - if opts.filterKey != "" && !strings.Contains(key, opts.filterKey) { - i += blockSize - blockCount++ - continue - } - - blockType := buf[0] - - encoded := buf[1:] - - var v []tsm1.Value - v, err := tsm1.DecodeBlock(buf, v) - if err != nil { - fmt.Printf("error: %v\n", err.Error()) - os.Exit(1) - } - startTime := time.Unix(0, v[0].UnixNano()) - - pointCount += int64(len(v)) - - // Length of the timestamp block - tsLen, j := binary.Uvarint(encoded) - - // Unpack the timestamp bytes - ts := encoded[int(j) : int(j)+int(tsLen)] - - // Unpack the value bytes - values := encoded[int(j)+int(tsLen):] - - tsEncoding := timeEnc[int(ts[0]>>4)] - vEncoding := encDescs[int(blockType+1)][values[0]>>4] - - typeDesc := blockTypes[blockType] - - blockStats.inc(0, ts[0]>>4) - blockStats.inc(int(blockType+1), values[0]>>4) - blockStats.size(len(buf)) - - if opts.dumpBlocks { - fmt.Fprintln(tw, " "+strings.Join([]string{ - strconv.FormatInt(blockCount, 10), - strconv.FormatUint(uint64(chksum), 10), - strconv.FormatInt(i, 10), - strconv.FormatInt(int64(len(buf)), 10), - typeDesc, - startTime.UTC().Format(time.RFC3339Nano), - strconv.FormatInt(int64(len(v)), 10), - fmt.Sprintf("%s/%s", tsEncoding, vEncoding), - fmt.Sprintf("%d/%d", len(ts), len(values)), - }, "\t")) - } - - i += blockSize - blockCount++ - } - } - - if opts.dumpBlocks { - println("Blocks:") - tw.Flush() - println() - } - - var blockSizeAvg int64 - if blockCount > 0 { - blockSizeAvg = blockSize / blockCount - } - fmt.Printf("Statistics\n") - fmt.Printf(" Blocks:\n") - fmt.Printf(" Total: %d Size: %d Min: %d Max: %d Avg: %d\n", - blockCount, blockSize, blockStats.min, blockStats.max, blockSizeAvg) - fmt.Printf(" Index:\n") - fmt.Printf(" Total: %d Size: %d\n", blockCount, indexSize) - fmt.Printf(" Points:\n") - fmt.Printf(" Total: %d", pointCount) - println() - - println(" Encoding:") - for i, counts := range blockStats.counts { - if len(counts) == 0 { - continue - } - fmt.Printf(" %s: ", strings.Title(fieldType[i])) - for j, v := range counts { - fmt.Printf("\t%s: %d (%d%%) ", encDescs[i][j], v, int(float64(v)/float64(blockCount)*100)) - } - println() - } - fmt.Printf(" Compression:\n") - fmt.Printf(" Per block: %0.2f bytes/point\n", float64(blockSize)/float64(pointCount)) - fmt.Printf(" Total: %0.2f bytes/point\n", float64(stat.Size())/float64(pointCount)) - - if len(errors) > 0 { - println() - fmt.Printf("Errors (%d):\n", len(errors)) - for _, err := range errors { - fmt.Printf(" * %v\n", err) - } - println() - } -} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/verify/verify.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/verify/verify.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/verify/verify.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/verify/verify.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,119 @@ +package verify + +import ( + "flag" + "fmt" + "hash/crc32" + "io" + "os" + "path/filepath" + "text/tabwriter" + "time" + + "github.com/influxdata/influxdb/tsdb/engine/tsm1" +) + +// Command represents the program execution for "influx_inspect verify". +type Command struct { + Stderr io.Writer + Stdout io.Writer +} + +// NewCommand returns a new instance of Command. +func NewCommand() *Command { + return &Command{ + Stderr: os.Stderr, + Stdout: os.Stdout, + } +} + +// Run executes the command. +func (cmd *Command) Run(args ...string) error { + var path string + fs := flag.NewFlagSet("verify", flag.ExitOnError) + fs.StringVar(&path, "dir", os.Getenv("HOME")+"/.influxdb", "Root storage path. [$HOME/.influxdb]") + + fs.SetOutput(cmd.Stdout) + fs.Usage = cmd.printUsage + + if err := fs.Parse(args); err != nil { + return err + } + + start := time.Now() + dataPath := filepath.Join(path, "data") + + brokenBlocks := 0 + totalBlocks := 0 + + // No need to do this in a loop + ext := fmt.Sprintf(".%s", tsm1.TSMFileExtension) + + // Get all TSM files by walking through the data dir + files := []string{} + err := filepath.Walk(dataPath, func(path string, f os.FileInfo, err error) error { + if err != nil { + return err + } + if filepath.Ext(path) == ext { + files = append(files, path) + } + return nil + }) + if err != nil { + panic(err) + } + + tw := tabwriter.NewWriter(cmd.Stdout, 16, 8, 0, '\t', 0) + + // Verify the checksums of every block in every file + for _, f := range files { + file, err := os.OpenFile(f, os.O_RDONLY, 0600) + if err != nil { + return err + } + + reader, err := tsm1.NewTSMReader(file) + if err != nil { + return err + } + + blockItr := reader.BlockIterator() + brokenFileBlocks := 0 + count := 0 + for blockItr.Next() { + totalBlocks++ + key, _, _, checksum, buf, err := blockItr.Read() + if err != nil { + brokenBlocks++ + fmt.Fprintf(tw, "%s: could not get checksum for key %v block %d due to error: %q\n", f, key, count, err) + } else if expected := crc32.ChecksumIEEE(buf); checksum != expected { + brokenBlocks++ + fmt.Fprintf(tw, "%s: got %d but expected %d for key %v, block %d\n", f, checksum, expected, key, count) + } + count++ + } + if brokenFileBlocks == 0 { + fmt.Fprintf(tw, "%s: healthy\n", f) + } + reader.Close() + } + + fmt.Fprintf(tw, "Broken Blocks: %d / %d, in %vs\n", brokenBlocks, totalBlocks, time.Since(start).Seconds()) + tw.Flush() + return nil +} + +// printUsage prints the usage message to STDERR. +func (cmd *Command) printUsage() { + usage := fmt.Sprintf(`Verifies the the checksum of shards. + +Usage: influx_inspect verify [flags] + + -dir + Root storage path + Defaults to "%[1]s/.influxdb". + `, os.Getenv("HOME")) + + fmt.Fprintf(cmd.Stdout, usage) +} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/verify/verify_test.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/verify/verify_test.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/verify/verify_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/verify/verify_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,3 @@ +package verify_test + +// TODO: write some tests diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_inspect/verify.go influxdb-1.1.1+dfsg1/cmd/influx_inspect/verify.go --- influxdb-1.0.2+dfsg1/cmd/influx_inspect/verify.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_inspect/verify.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -package main - -import ( - "fmt" - "hash/crc32" - "os" - "path/filepath" - "text/tabwriter" - "time" - - "github.com/influxdata/influxdb/tsdb/engine/tsm1" -) - -func cmdVerify(path string) { - start := time.Now() - dataPath := filepath.Join(path, "data") - - brokenBlocks := 0 - totalBlocks := 0 - - // No need to do this in a loop - ext := fmt.Sprintf(".%s", tsm1.TSMFileExtension) - - // Get all TSM files by walking through the data dir - files := []string{} - err := filepath.Walk(dataPath, func(path string, f os.FileInfo, err error) error { - if err != nil { - return err - } - if filepath.Ext(path) == ext { - files = append(files, path) - } - return nil - }) - if err != nil { - panic(err) - } - - tw := tabwriter.NewWriter(os.Stdout, 16, 8, 0, '\t', 0) - - // Verify the checksums of every block in every file - for _, f := range files { - file, err := os.OpenFile(f, os.O_RDONLY, 0600) - if err != nil { - fmt.Printf("%v", err) - os.Exit(1) - } - - reader, err := tsm1.NewTSMReader(file) - if err != nil { - fmt.Printf("%v", err) - os.Exit(1) - } - - blockItr := reader.BlockIterator() - brokenFileBlocks := 0 - count := 0 - for blockItr.Next() { - totalBlocks++ - key, _, _, checksum, buf, err := blockItr.Read() - if err != nil { - brokenBlocks++ - fmt.Fprintf(tw, "%s: could not get checksum for key %v block %d due to error: %q\n", f, key, count, err) - } else if expected := crc32.ChecksumIEEE(buf); checksum != expected { - brokenBlocks++ - fmt.Fprintf(tw, "%s: got %d but expected %d for key %v, block %d\n", f, checksum, expected, key, count) - } - count++ - } - if brokenFileBlocks == 0 { - fmt.Fprintf(tw, "%s: healthy\n", f) - } - reader.Close() - } - - fmt.Fprintf(tw, "Broken Blocks: %d / %d, in %vs\n", brokenBlocks, totalBlocks, time.Since(start).Seconds()) - tw.Flush() -} diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_stress/influx_stress.go influxdb-1.1.1+dfsg1/cmd/influx_stress/influx_stress.go --- influxdb-1.0.2+dfsg1/cmd/influx_stress/influx_stress.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_stress/influx_stress.go 2016-12-06 21:36:15.000000000 +0000 @@ -52,7 +52,7 @@ c.Read.QueryClients.Basic.Database = *db } - w := stress.NewWriter(&c.Write.PointGenerators.Basic, &c.Write.InfluxClients.Basic) + w := stress.NewWriter(c.Write.PointGenerators.Basic, &c.Write.InfluxClients.Basic) r := stress.NewQuerier(&c.Read.QueryGenerators.Basic, &c.Read.QueryClients.Basic) s := stress.NewStressTest(&c.Provision.Basic, w, r) diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_tsm/b1/reader.go influxdb-1.1.1+dfsg1/cmd/influx_tsm/b1/reader.go --- influxdb-1.0.2+dfsg1/cmd/influx_tsm/b1/reader.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_tsm/b1/reader.go 2016-12-06 21:36:15.000000000 +0000 @@ -12,6 +12,7 @@ "github.com/influxdata/influxdb/tsdb/engine/tsm1" ) +// DefaultChunkSize is the size of chunks read from the b1 shard const DefaultChunkSize int = 1000 var excludedBuckets = map[string]bool{ diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_tsm/main.go influxdb-1.1.1+dfsg1/cmd/influx_tsm/main.go --- influxdb-1.0.2+dfsg1/cmd/influx_tsm/main.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_tsm/main.go 2016-12-06 21:36:15.000000000 +0000 @@ -57,7 +57,7 @@ SkipBackup bool UpdateInterval time.Duration Yes bool - CpuFile string + CPUFile string } func (o *options) Parse() error { @@ -73,7 +73,7 @@ fs.StringVar(&opts.DebugAddr, "debug", "", "If set, http debugging endpoints will be enabled on the given address") fs.DurationVar(&opts.UpdateInterval, "interval", 5*time.Second, "How often status updates are printed.") fs.BoolVar(&opts.Yes, "y", false, "Don't ask, just convert") - fs.StringVar(&opts.CpuFile, "profile", "", "CPU Profile location") + fs.StringVar(&opts.CPUFile, "profile", "", "CPU Profile location") fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %v [options] \n", os.Args[0]) fmt.Fprintf(os.Stderr, "%v\n\nOptions:\n", description) @@ -217,8 +217,8 @@ } fmt.Println("Conversion starting....") - if opts.CpuFile != "" { - f, err := os.Create(opts.CpuFile) + if opts.CPUFile != "" { + f, err := os.Create(opts.CPUFile) if err != nil { log.Fatal(err) } diff -Nru influxdb-1.0.2+dfsg1/cmd/influx_tsm/stats/stats.go influxdb-1.1.1+dfsg1/cmd/influx_tsm/stats/stats.go --- influxdb-1.0.2+dfsg1/cmd/influx_tsm/stats/stats.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/influx_tsm/stats/stats.go 2016-12-06 21:36:15.000000000 +0000 @@ -18,30 +18,37 @@ TotalTime time.Duration } +// AddPointsRead increments the number of read points. func (s *Stats) AddPointsRead(n int) { atomic.AddUint64(&s.PointsRead, uint64(n)) } +// AddPointsWritten increments the number of written points. func (s *Stats) AddPointsWritten(n int) { atomic.AddUint64(&s.PointsWritten, uint64(n)) } +// AddTSMBytes increments the number of TSM Bytes. func (s *Stats) AddTSMBytes(n uint32) { atomic.AddUint64(&s.TsmBytesWritten, uint64(n)) } +// IncrTSMFileCount increments the number of TSM files created. func (s *Stats) IncrTSMFileCount() { atomic.AddUint64(&s.TsmFilesCreated, 1) } +// IncrNaN increments the number of NaNs filtered. func (s *Stats) IncrNaN() { atomic.AddUint64(&s.NanFiltered, 1) } +// IncrInf increments the number of Infs filtered. func (s *Stats) IncrInf() { atomic.AddUint64(&s.InfFiltered, 1) } +// IncrFiltered increments the number of fields filtered. func (s *Stats) IncrFiltered() { atomic.AddUint64(&s.FieldsFiltered, 1) } diff -Nru influxdb-1.0.2+dfsg1/cmd/parse.go influxdb-1.1.1+dfsg1/cmd/parse.go --- influxdb-1.0.2+dfsg1/cmd/parse.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/cmd/parse.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,28 @@ +package cmd + +import "strings" + +// ParseCommandName extracts the command name and args from the args list. +func ParseCommandName(args []string) (string, []string) { + // Retrieve command name as first argument. + var name string + if len(args) > 0 { + if !strings.HasPrefix(args[0], "-") { + name = args[0] + } else if args[0] == "-h" || args[0] == "-help" || args[0] == "--help" { + // Special case -h immediately following binary name + name = "help" + } + } + + // If command is "help" and has an argument then rewrite args to use "-h". + if name == "help" && len(args) > 2 && !strings.HasPrefix(args[1], "-") { + return args[1], []string{"-h"} + } + + // If a named command is specified then return it with its arguments. + if name != "" { + return name, args[1:] + } + return "", args +} diff -Nru influxdb-1.0.2+dfsg1/CONTRIBUTING.md influxdb-1.1.1+dfsg1/CONTRIBUTING.md --- influxdb-1.0.2+dfsg1/CONTRIBUTING.md 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/CONTRIBUTING.md 2016-12-06 21:36:15.000000000 +0000 @@ -69,7 +69,7 @@ Installing Go ------------- -InfluxDB requires Go 1.6.2. +InfluxDB requires Go 1.7.4. At InfluxDB we find gvm, a Go version manager, useful for installing Go. For instructions on how to install it see [the gvm page on github](https://github.com/moovweb/gvm). @@ -77,8 +77,8 @@ After installing gvm you can install and set the default go version by running the following: - gvm install go1.6.2 - gvm use go1.6.2 --default + gvm install go1.7.4 + gvm use go1.7.4 --default Installing GDM ------------- diff -Nru influxdb-1.0.2+dfsg1/coordinator/points_writer.go influxdb-1.1.1+dfsg1/coordinator/points_writer.go --- influxdb-1.0.2+dfsg1/coordinator/points_writer.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/coordinator/points_writer.go 2016-12-06 21:36:15.000000000 +0000 @@ -84,7 +84,7 @@ // AddPoint adds a point to the WritePointRequest with field key 'value' func (w *WritePointsRequest) AddPoint(name string, value interface{}, timestamp time.Time, tags map[string]string) { pt, err := models.NewPoint( - name, tags, map[string]interface{}{"value": value}, timestamp, + name, models.NewTags(tags), map[string]interface{}{"value": value}, timestamp, ) if err != nil { return @@ -118,12 +118,7 @@ // MapPoint maps a point to shard func (s *ShardMapping) MapPoint(shardInfo *meta.ShardInfo, p models.Point) { - points, ok := s.Points[shardInfo.ID] - if !ok { - s.Points[shardInfo.ID] = []models.Point{p} - } else { - s.Points[shardInfo.ID] = append(points, p) - } + s.Points[shardInfo.ID] = append(s.Points[shardInfo.ID], p) s.Shards[shardInfo.ID] = shardInfo } @@ -267,7 +262,9 @@ // - (assuming identical end times) the shard group with the earliest start // time. idx := sort.Search(len(l), func(i int) bool { return l[i].EndTime.After(t) }) - if idx == len(l) { + + // We couldn't find a shard group the point falls into. + if idx == len(l) || t.Before(l[idx].StartTime) { return nil } return &l[idx] @@ -304,8 +301,7 @@ return err } - // Write each shard in it's own goroutine and return as soon - // as one fails. + // Write each shard in it's own goroutine and return as soon as one fails. ch := make(chan error, len(shardMappings.Points)) for shardID, points := range shardMappings.Points { go func(shard *meta.ShardInfo, database, retentionPolicy string, points []models.Point) { diff -Nru influxdb-1.0.2+dfsg1/coordinator/points_writer_internal_test.go influxdb-1.1.1+dfsg1/coordinator/points_writer_internal_test.go --- influxdb-1.0.2+dfsg1/coordinator/points_writer_internal_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/coordinator/points_writer_internal_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,46 @@ +package coordinator + +import ( + "testing" + "time" +) + +func TestSgList_ShardGroupAt(t *testing.T) { + base := time.Date(2016, 10, 19, 0, 0, 0, 0, time.UTC) + day := func(n int) time.Time { + return base.Add(time.Duration(24*n) * time.Hour) + } + + list := sgList{ + {ID: 1, StartTime: day(0), EndTime: day(1)}, + {ID: 2, StartTime: day(1), EndTime: day(2)}, + {ID: 3, StartTime: day(2), EndTime: day(3)}, + // SG day 3 to day 4 missing... + {ID: 4, StartTime: day(4), EndTime: day(5)}, + {ID: 5, StartTime: day(5), EndTime: day(6)}, + } + + examples := []struct { + T time.Time + ShardGroupID uint64 // 0 will indicate we don't expect a shard group + }{ + {T: base.Add(-time.Minute), ShardGroupID: 0}, // Before any SG + {T: day(0), ShardGroupID: 1}, + {T: day(0).Add(time.Minute), ShardGroupID: 1}, + {T: day(1), ShardGroupID: 2}, + {T: day(3).Add(time.Minute), ShardGroupID: 0}, // No matching SG + {T: day(5).Add(time.Hour), ShardGroupID: 5}, + } + + for i, example := range examples { + sg := list.ShardGroupAt(example.T) + var id uint64 + if sg != nil { + id = sg.ID + } + + if got, exp := id, example.ShardGroupID; got != exp { + t.Errorf("[Example %d] got %v, expected %v", i+1, got, exp) + } + } +} diff -Nru influxdb-1.0.2+dfsg1/coordinator/statement_executor.go influxdb-1.1.1+dfsg1/coordinator/statement_executor.go --- influxdb-1.0.2+dfsg1/coordinator/statement_executor.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/coordinator/statement_executor.go 2016-12-06 21:36:15.000000000 +0000 @@ -187,12 +187,11 @@ return err } - ctx.Results <- &influxql.Result{ + return ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, Series: rows, Messages: messages, - } - return nil + }) } func (e *StatementExecutor) executeAlterRetentionPolicyStatement(stmt *influxql.AlterRetentionPolicyStatement) error { @@ -455,16 +454,14 @@ } // Send results or exit if closing. - select { - case <-ctx.InterruptCh: - return influxql.ErrQueryInterrupted - case ctx.Results <- result: + if err := ctx.Send(result); err != nil { + return err } emitted = true } - // Flush remaing points and emit write count if an INTO statement. + // Flush remaining points and emit write count if an INTO statement. if stmt.Target != nil { if err := pointsWriter.Flush(); err != nil { return err @@ -475,7 +472,7 @@ messages = append(messages, influxql.ReadOnlyWarning(stmt.String())) } - ctx.Results <- &influxql.Result{ + return ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, Messages: messages, Series: []*models.Row{{ @@ -483,16 +480,15 @@ Columns: []string{"time", "written"}, Values: [][]interface{}{{time.Unix(0, 0).UTC(), writeN}}, }}, - } - return nil + }) } // Always emit at least one result. if !emitted { - ctx.Results <- &influxql.Result{ + return ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, Series: make([]*models.Row, 0), - } + }) } return nil @@ -529,7 +525,13 @@ if influxql.Sources(stmt.Sources).HasSystemSource() { opt.MaxTime = time.Unix(0, influxql.MaxTime).UTC() } else { - opt.MaxTime = now + if interval, err := stmt.GroupByInterval(); err != nil { + return nil, stmt, err + } else if interval > 0 { + opt.MaxTime = now + } else { + opt.MaxTime = time.Unix(0, influxql.MaxTime).UTC() + } } } if opt.MinTime.IsZero() { @@ -542,6 +544,9 @@ // Remove "time" from fields list. stmt.RewriteTimeFields() + // Rewrite any regex conditions that could make use of the index. + stmt.RewriteRegexConditions() + // Create an iterator creator based on the shards in the cluster. ic, err := e.iteratorCreator(stmt, &opt) if err != nil { @@ -578,7 +583,7 @@ // Determine the number of buckets by finding the time span and dividing by the interval. buckets := int64(max.Sub(min)) / int64(interval) if int(buckets) > e.MaxSelectBucketsN { - return nil, stmt, fmt.Errorf("max select bucket count exceeded: %d buckets", buckets) + return nil, stmt, fmt.Errorf("max-select-buckets limit exceeded: (%d/%d)", buckets, e.MaxSelectBucketsN) } } } @@ -672,17 +677,16 @@ } func (e *StatementExecutor) executeShowMeasurementsStatement(q *influxql.ShowMeasurementsStatement, ctx *influxql.ExecutionContext) error { - if ctx.Database == "" { + if q.Database == "" { return ErrDatabaseNameRequired } - measurements, err := e.TSDBStore.Measurements(ctx.Database, q.Condition) + measurements, err := e.TSDBStore.Measurements(q.Database, q.Condition) if err != nil || len(measurements) == 0 { - ctx.Results <- &influxql.Result{ + return ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, Err: err, - } - return nil + }) } if q.Offset > 0 { @@ -705,24 +709,26 @@ } if len(values) == 0 { - ctx.Results <- &influxql.Result{ + return ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, - } - return nil + }) } - ctx.Results <- &influxql.Result{ + return ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, Series: []*models.Row{{ Name: "measurements", Columns: []string{"name"}, Values: values, }}, - } - return nil + }) } func (e *StatementExecutor) executeShowRetentionPoliciesStatement(q *influxql.ShowRetentionPoliciesStatement) (models.Rows, error) { + if q.Database == "" { + return nil, ErrDatabaseNameRequired + } + di := e.MetaClient.Database(q.Database) if di == nil { return nil, influxdb.ErrDatabaseNotFound(q.Database) @@ -844,17 +850,16 @@ } func (e *StatementExecutor) executeShowTagValues(q *influxql.ShowTagValuesStatement, ctx *influxql.ExecutionContext) error { - if ctx.Database == "" { + if q.Database == "" { return ErrDatabaseNameRequired } - tagValues, err := e.TSDBStore.TagValues(ctx.Database, q.Condition) + tagValues, err := e.TSDBStore.TagValues(q.Database, q.Condition) if err != nil { - ctx.Results <- &influxql.Result{ + return ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, Err: err, - } - return nil + }) } emitted := false @@ -888,18 +893,20 @@ row.Values[i] = []interface{}{v.Key, v.Value} } - ctx.Results <- &influxql.Result{ + if err := ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, Series: []*models.Row{row}, + }); err != nil { + return err } emitted = true } // Ensure at least one result is emitted. if !emitted { - ctx.Results <- &influxql.Result{ + return ctx.Send(&influxql.Result{ StatementID: ctx.StatementID, - } + }) } return nil } @@ -1049,7 +1056,7 @@ } } - p, err := models.NewPoint(measurementName, row.Tags, vals, v[timeIndex].(time.Time)) + p, err := models.NewPoint(measurementName, models.NewTags(row.Tags), vals, v[timeIndex].(time.Time)) if err != nil { // Drop points that can't be stored continue @@ -1068,8 +1075,26 @@ return } switch node := node.(type) { + case *influxql.ShowRetentionPoliciesStatement: + if node.Database == "" { + node.Database = defaultDatabase + } + case *influxql.ShowMeasurementsStatement: + if node.Database == "" { + node.Database = defaultDatabase + } + case *influxql.ShowTagValuesStatement: + if node.Database == "" { + node.Database = defaultDatabase + } case *influxql.Measurement: - err = e.normalizeMeasurement(node, defaultDatabase) + switch stmt.(type) { + case *influxql.DropSeriesStatement, *influxql.DeleteSeriesStatement: + // DB and RP not supported by these statements so don't rewrite into invalid + // statements + default: + err = e.normalizeMeasurement(node, defaultDatabase) + } } }) return diff -Nru influxdb-1.0.2+dfsg1/coordinator/statement_executor_test.go influxdb-1.1.1+dfsg1/coordinator/statement_executor_test.go --- influxdb-1.0.2+dfsg1/coordinator/statement_executor_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/coordinator/statement_executor_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -13,6 +13,7 @@ "github.com/davecgh/go-spew/spew" "github.com/influxdata/influxdb/coordinator" "github.com/influxdata/influxdb/influxql" + "github.com/influxdata/influxdb/internal" "github.com/influxdata/influxdb/models" "github.com/influxdata/influxdb/services/meta" "github.com/influxdata/influxdb/tsdb" @@ -100,13 +101,79 @@ if a := ReadAllResults(e.ExecuteQuery(`SELECT count(value) FROM cpu WHERE time >= '2000-01-01T00:00:05Z' AND time < '2000-01-01T00:00:35Z' GROUP BY time(10s)`, "db0", 0)); !reflect.DeepEqual(a, []*influxql.Result{ { StatementID: 0, - Err: errors.New("max select bucket count exceeded: 4 buckets"), + Err: errors.New("max-select-buckets limit exceeded: (4/3)"), }, }) { t.Fatalf("unexpected results: %s", spew.Sdump(a)) } } +func TestStatementExecutor_NormalizeDropSeries(t *testing.T) { + q, err := influxql.ParseQuery("DROP SERIES FROM cpu") + if err != nil { + t.Fatalf("unexpected error parsing query: %v", err) + } + + stmt := q.Statements[0].(*influxql.DropSeriesStatement) + + s := &coordinator.StatementExecutor{ + MetaClient: &internal.MetaClientMock{ + DatabaseFn: func(name string) *meta.DatabaseInfo { + t.Fatal("meta client should not be called") + return nil + }, + }, + } + if err := s.NormalizeStatement(stmt, "foo"); err != nil { + t.Fatalf("unexpected error normalizing statement: %v", err) + } + + m := stmt.Sources[0].(*influxql.Measurement) + if m.Database != "" { + t.Fatalf("database rewritten when not supposed to: %v", m.Database) + } + if m.RetentionPolicy != "" { + t.Fatalf("database rewritten when not supposed to: %v", m.RetentionPolicy) + } + + if exp, got := "DROP SERIES FROM cpu", q.String(); exp != got { + t.Fatalf("generated query does match parsed: exp %v, got %v", exp, got) + } +} + +func TestStatementExecutor_NormalizeDeleteSeries(t *testing.T) { + q, err := influxql.ParseQuery("DELETE FROM cpu") + if err != nil { + t.Fatalf("unexpected error parsing query: %v", err) + } + + stmt := q.Statements[0].(*influxql.DeleteSeriesStatement) + + s := &coordinator.StatementExecutor{ + MetaClient: &internal.MetaClientMock{ + DatabaseFn: func(name string) *meta.DatabaseInfo { + t.Fatal("meta client should not be called") + return nil + }, + }, + } + if err := s.NormalizeStatement(stmt, "foo"); err != nil { + t.Fatalf("unexpected error normalizing statement: %v", err) + } + + m := stmt.Sources[0].(*influxql.Measurement) + if m.Database != "" { + t.Fatalf("database rewritten when not supposed to: %v", m.Database) + } + if m.RetentionPolicy != "" { + t.Fatalf("database rewritten when not supposed to: %v", m.RetentionPolicy) + } + + if exp, got := "DELETE FROM cpu", q.String(); exp != got { + t.Fatalf("generated query does match parsed: exp %v, got %v", exp, got) + } +} + // QueryExecutor is a test wrapper for coordinator.QueryExecutor. type QueryExecutor struct { *influxql.QueryExecutor diff -Nru influxdb-1.0.2+dfsg1/debian/changelog influxdb-1.1.1+dfsg1/debian/changelog --- influxdb-1.0.2+dfsg1/debian/changelog 2016-10-25 17:19:04.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/changelog 2016-12-22 05:50:08.000000000 +0000 @@ -1,4 +1,29 @@ +influxdb (1.1.1+dfsg1-2) unstable; urgency=medium + + * Lintian overrides. + + -- Alexandre Viau Thu, 22 Dec 2016 00:50:08 -0500 + +influxdb (1.1.1+dfsg1-1) unstable; urgency=medium + + [ Alexandre Viau ] + * Import Guillem's work. + * Refresh jwt-v2.patch. + * Update influxdb.conf. + * Depend on newer golang-github-jwilder-encoding. + * Adapt disable-reporting.patch. + * Copy over iql files. + * Fix tests in jwt-v2.patch. + + [ Guillem Jover ] + * New upstream release. (Closes: #846576) + * Fix build to work on github.com/dgrijalva/jwt-go v2. + * Pass --no-close to start-stop-daemon --start to get actual logging. + + -- Alexandre Viau Tue, 20 Dec 2016 21:25:35 -0500 + influxdb (1.0.2+dfsg1-1) unstable; urgency=medium + [ Alexandre Viau ] * Update default configuration file. diff -Nru influxdb-1.0.2+dfsg1/debian/control influxdb-1.1.1+dfsg1/debian/control --- influxdb-1.0.2+dfsg1/debian/control 2016-10-25 17:19:04.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/control 2016-12-22 05:50:08.000000000 +0000 @@ -29,7 +29,7 @@ golang-github-dgrijalva-jwt-go-dev, golang-github-dgryski-go-bitstream-dev, golang-github-dgryski-go-bits-dev, - golang-github-jwilder-encoding-dev (>= 0.0~git20160426.0.ac74639), + golang-github-jwilder-encoding-dev (>= 0.0~git20160927.0.4dada27), golang-github-influxdb-enterprise-client-dev, golang-github-paulbellamy-ratecounter-dev, golang-github-influxdb-usage-client-dev (>= 0.0~git20151204.0.475977e-2~), @@ -60,7 +60,7 @@ golang-github-dgrijalva-jwt-go-dev, golang-github-dgryski-go-bitstream-dev, golang-github-dgryski-go-bits-dev, - golang-github-jwilder-encoding-dev (>= 0.0~git20160426.0.ac74639), + golang-github-jwilder-encoding-dev (>= 0.0~git20160927.0.4dada27), golang-github-influxdb-enterprise-client-dev, golang-github-paulbellamy-ratecounter-dev, golang-github-influxdb-usage-client-dev, diff -Nru influxdb-1.0.2+dfsg1/debian/influxdb.conf influxdb-1.1.1+dfsg1/debian/influxdb.conf --- influxdb-1.0.2+dfsg1/debian/influxdb.conf 2016-10-25 17:19:04.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/influxdb.conf 2016-12-22 05:50:08.000000000 +0000 @@ -1,5 +1,10 @@ ### Welcome to the InfluxDB configuration file. +# The values in this file override the default values used by the system if +# a config option is not specified. The commented out lines are the the configuration +# field and the default value used. Uncommentting a line and changing the value +# will change the value used at runtime when the process is restarted. + # Once every 24 hours InfluxDB will report usage data to usage.influxdata.com # The data includes a random ID, os, arch, version, the number of series and other # usage data. No data from user databases is ever transmitted. @@ -22,14 +27,11 @@ # Where the metadata/raft database is stored dir = "/var/lib/influxdb/meta" - retention-autocreate = true + # Automatically create a default retention policy when creating a database. + # retention-autocreate = true # If log messages are printed for the meta service - logging-enabled = true - pprof-enabled = false - - # The default duration for leases. - lease-duration = "1m0s" + # logging-enabled = true ### ### [data] @@ -41,14 +43,11 @@ ### [data] - # Controls if this node holds time series data shards in the cluster - enabled = true - + # The directory where the TSM storage engine stores TSM files. dir = "/var/lib/influxdb/data" - # These are the WAL settings for the storage engine >= 0.9.3 + # The directory where the TSM storage engine stores WAL files. wal-dir = "/var/lib/influxdb/wal" - wal-logging-enabled = true # Trace logging provides more verbose output around the tsm engine. Turning # this on can provide more useful output for debugging tsm engine issues. @@ -62,7 +61,7 @@ # CacheMaxMemorySize is the maximum size a shard's cache can # reach before it starts rejecting writes. - # cache-max-memory-size = 524288000 + # cache-max-memory-size = 1048576000 # CacheSnapshotMemorySize is the size at which the engine will # snapshot the cache and write it to a TSM file, freeing up memory @@ -71,21 +70,22 @@ # CacheSnapshotWriteColdDuration is the length of time at # which the engine will snapshot the cache and write it to # a new TSM file if the shard hasn't received writes or deletes - # cache-snapshot-write-cold-duration = "1h" - - # MinCompactionFileCount is the minimum number of TSM files - # that need to exist before a compaction cycle will run - # compact-min-file-count = 3 + # cache-snapshot-write-cold-duration = "10m" # CompactFullWriteColdDuration is the duration at which the engine # will compact all TSM files in a shard if it hasn't received a # write or delete - # compact-full-write-cold-duration = "24h" + # compact-full-write-cold-duration = "4h" - # MaxPointsPerBlock is the maximum number of points in an encoded - # block in a TSM file. Larger numbers may yield better compression - # but could incur a performance penalty when querying - # max-points-per-block = 1000 + # The maximum series allowed per database before writes are dropped. This limit can prevent + # high cardinality issues at the database level. This limit can be disabled by setting it to + # 0. + # max-series-per-database = 1000000 + + # The maximum number of tag values per tag that are allowed before writes are dropped. This limit + # can prevent high cardinality tag values from being written to a measurement. This limit can be + # disabled by setting it to 0. + # max-values-per-tag = 100000 ### ### [coordinator] @@ -93,14 +93,37 @@ ### Controls the clustering service configuration. ### -[coordinator] - write-timeout = "10s" - max-concurrent-queries = 0 - query-timeout = "0" - log-queries-after = "0" - max-select-point = 0 - max-select-series = 0 - max-select-buckets = 0 +# [coordinator] + # The default time a write request will wait until a "timeout" error is returned to the caller. + # write-timeout = "10s" + + # The maximum number of concurrent queries allowed to be executing at one time. If a query is + # executed and exceeds this limit, an error is returned to the caller. This limit can be disabled + # by setting it to 0. + # max-concurrent-queries = 0 + + # The maximum time a query will is allowed to execute before being killed by the system. This limit + # can help prevent run away queries. Setting the value to 0 disables the limit. + # query-timeout = "0s" + + # The the time threshold when a query will be logged as a slow query. This limit can be set to help + # discover slow or resource intensive queries. Setting the value to 0 disables the slow query logging. + # log-queries-after = "0s" + + # The maximum number of points a SELECT can process. A value of 0 will make the maximum + # point count unlimited. + # max-select-point = 0 + + # The maximum number of series a SELECT can run. A value of 0 will make the maximum series + # count unlimited. + + # The maximum number of series a SELECT can run. A value of zero will make the maximum series + # count unlimited. + # max-select-series = 0 + + # The maxium number of group by time bucket a SELECt can create. A value of zero will max the maximum + # number of buckets unlimited. + # max-select-buckets = 0 ### ### [retention] @@ -108,9 +131,12 @@ ### Controls the enforcement of retention policies for evicting old data. ### -[retention] - enabled = true - check-interval = "30m" +# [retention] + # Determines whether retention policy enforcment enabled. + # enabled = true + + # The interval of time when retention policy enforcement checks run. + # check-interval = "30m" ### ### [shard-precreation] @@ -120,10 +146,16 @@ ### future, will ever be created. Shards are never precreated that would be wholly ### or partially in the past. -[shard-precreation] - enabled = true - check-interval = "10m" - advance-period = "30m" +# [shard-precreation] + # Determines whether shard pre-creation service is enabled. + # enabled = true + + # The interval of time when the check to pre-create new shards runs. + # check-interval = "10m" + + # The default period ahead of the endtime of a shard group that its successor + # group is created. + # advance-period = "30m" ### ### Controls the system self-monitoring, statistics and diagnostics. @@ -134,10 +166,15 @@ ### and a replication factor of 1, if it does not exist. In all cases the ### this retention policy is configured as the default for the database. -[monitor] - store-enabled = true # Whether to record statistics internally. - store-database = "_internal" # The destination database for recorded statistics - store-interval = "10s" # The interval at which to record statistics +# [monitor] + # Whether to record statistics internally. + # store-enabled = true + + # The destination database for recorded statistics + # store-database = "_internal" + + # The interval at which to record statistics + # store-interval = "10s" ### ### [admin] @@ -145,12 +182,20 @@ ### Controls the availability of the built-in, web-based admin interface. If HTTPS is ### enabled for the admin interface, HTTPS must also be enabled on the [http] service. ### +### NOTE: This interface is deprecated as of 1.1.0 and will be removed in a future release. + +# [admin] + # Determines whether the admin service is enabled. + # enabled = false + + # The default bind address used by the admin service. + # bind-address = ":8083" -[admin] - enabled = true - bind-address = ":8083" - https-enabled = false - https-certificate = "/etc/ssl/influxdb.pem" + # Whether the admin service should use HTTPS. + # https-enabled = false + + # The SSL certificate used when HTTPS is enabled. + # https-certificate = "/etc/ssl/influxdb.pem" ### ### [http] @@ -159,19 +204,53 @@ ### mechanism for getting data into and out of InfluxDB. ### -[http] - enabled = true - bind-address = ":8086" - auth-enabled = false - log-enabled = true - write-tracing = false - pprof-enabled = false - https-enabled = false - https-certificate = "/etc/ssl/influxdb.pem" - ### Use a separate private key location. +# [http] + # Determines whether HTTP endpoint is enabled. + # enabled = true + + # The bind address used by the HTTP service. + # bind-address = ":8086" + + # Determines whether HTTP authentication is enabled. + # auth-enabled = false + + # The default realm sent back when issuing a basic auth challenge. + # realm = "InfluxDB" + + # Determines whether HTTP request logging is enable.d + # log-enabled = true + + # Determines whether detailed write logging is enabled. + # write-tracing = false + + # Determines whether the pprof endpoint is enabled. This endpoint is used for + # troubleshooting and monitoring. + # pprof-enabled = true + + # Determines whether HTTPS is enabled. + # https-enabled = false + + # The SSL certificate to use when HTTPS is enabled. + # https-certificate = "/etc/ssl/influxdb.pem" + + # Use a separate private key location. # https-private-key = "" - max-row-limit = 10000 - realm = "InfluxDB" + + # The JWT auth shared secret to validate requests using JSON web tokens. + # shared-sercret = "" + + # The default chunk size for result sets that should be chunked. + # max-row-limit = 10000 + + # The maximum number of HTTP connections that may be open at once. New connections that + # would exceed this limit are dropped. Setting this value to 0 disables the limit. + # max-connection-limit = 0 + + # Enable http service over unix domain socket + # unix-socket-enabled = false + + # The path of the unix domain socket. + # bind-socket = "/var/run/influxdb.sock" ### ### [subscriber] @@ -180,10 +259,24 @@ ### received by the InfluxDB host. ### -[subscriber] - enabled = true +# [subscriber] + # Determines whether the subscriber service is enabled. + # enabled = true + + # The default timeout for HTTP writes to subscribers. # http-timeout = "30s" + + # Allows insecure HTTPS connections to subscribers. This is useful when testing with self- + # signed certificates. + # insecure-skip-verify = false + + # The path to the PEM encoded CA certs file. If the empty string, the default system certs will be used + # ca-certs = "" + + # The number of writer goroutines processing the write channel. # write-concurrency = 40 + + # The number of in-flight writes buffered in the write channel. # write-buffer-size = 1000 @@ -193,9 +286,11 @@ ### Controls one or many listeners for Graphite data. ### -[[graphite]] - enabled = false +# [[graphite]] + # Determines whether the graphite endpoint is enabled. + # enabled = false # database = "graphite" + # retention-policy = "" # bind-address = ":2003" # protocol = "tcp" # consistency-level = "one" @@ -204,10 +299,17 @@ # otherwise you could get dropped metrics or poor performance. Batching # will buffer points in memory if you have many coming in. - # batch-size = 5000 # will flush if this many points get buffered - # batch-pending = 10 # number of batches that may be pending in memory - # batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit - # udp-read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # Flush if this many points get buffered + # batch-size = 5000 + + # number of batches that may be pending in memory + # batch-pending = 10 + + # Flush at least this often even if we haven't hit buffer limit + # batch-timeout = "1s" + + # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # udp-read-buffer = 0 ### This string joins multiple matching 'measurement' values providing more control over the final measurement name. # separator = "." @@ -232,20 +334,28 @@ ### Controls one or many listeners for collectd data. ### -[[collectd]] - enabled = false - # bind-address = "" - # database = "" - # typesdb = "" +# [[collectd]] + # enabled = false + # bind-address = ":25826" + # database = "collectd" + # retention-policy = "" + # typesdb = "/usr/share/collectd/types.db" # These next lines control how batching works. You should have this enabled # otherwise you could get dropped metrics or poor performance. Batching # will buffer points in memory if you have many coming in. - # batch-size = 1000 # will flush if this many points get buffered - # batch-pending = 5 # number of batches that may be pending in memory - # batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit - # read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # Flush if this many points get buffered + # batch-size = 5000 + + # Number of batches that may be pending in memory + # batch-pending = 10 + + # Flush at least this often even if we haven't hit buffer limit + # batch-timeout = "10s" + + # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # read-buffer = 0 ### ### [opentsdb] @@ -253,23 +363,30 @@ ### Controls one or many listeners for OpenTSDB data. ### -[[opentsdb]] - enabled = false +# [[opentsdb]] + # enabled = false # bind-address = ":4242" # database = "opentsdb" # retention-policy = "" # consistency-level = "one" # tls-enabled = false - # certificate= "" - # log-point-errors = true # Log an error for every malformed point. + # certificate= "/etc/ssl/influxdb.pem" + + # Log an error for every malformed point. + # log-point-errors = true # These next lines control how batching works. You should have this enabled # otherwise you could get dropped metrics or poor performance. Only points # metrics received over the telnet protocol undergo batching. - # batch-size = 1000 # will flush if this many points get buffered - # batch-pending = 5 # number of batches that may be pending in memory - # batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit + # Flush if this many points get buffered + # batch-size = 1000 + + # Number of batches that may be pending in memory + # batch-pending = 5 + + # Flush at least this often even if we haven't hit buffer limit + # batch-timeout = "1s" ### ### [[udp]] @@ -277,9 +394,9 @@ ### Controls the listeners for InfluxDB line protocol data via UDP. ### -[[udp]] - enabled = false - # bind-address = "" +# [[udp]] + # enabled = false + # bind-address = ":8089" # database = "udp" # retention-policy = "" @@ -287,13 +404,17 @@ # otherwise you could get dropped metrics or poor performance. Batching # will buffer points in memory if you have many coming in. - # batch-size = 1000 # will flush if this many points get buffered - # batch-pending = 5 # number of batches that may be pending in memory - # batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit - # read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # Flush if this many points get buffered + # batch-size = 5000 + + # Number of batches that may be pending in memory + # batch-pending = 10 + + # Will flush at least this often even if we haven't hit buffer limit + # batch-timeout = "1s" - # set the expected UDP payload size; lower values tend to yield better performance, default is max UDP size 65536 - # udp-payload-size = 65536 + # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # read-buffer = 0 ### ### [continuous_queries] @@ -301,7 +422,12 @@ ### Controls how continuous queries are run within InfluxDB. ### -[continuous_queries] - log-enabled = true - enabled = true - # run-interval = "1s" # interval for how often continuous queries will be checked if they need to run +# [continuous_queries] + # Determiens whether the continuous query service is enabled. + # enabled = true + + # Controls whether queries are logged when executed by the CQ service. + # log-enabled = true + + # interval for how often continuous queries will be checked if they need to run + # run-interval = "1s" diff -Nru influxdb-1.0.2+dfsg1/debian/influxdb.init influxdb-1.1.1+dfsg1/debian/influxdb.init --- influxdb-1.0.2+dfsg1/debian/influxdb.init 2016-10-25 17:19:04.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/influxdb.init 2016-12-22 05:50:08.000000000 +0000 @@ -94,7 +94,7 @@ fi start-stop-daemon --start --quiet --oknodo --exec $daemon \ - --chuid $GROUP:$USER --pidfile $pidfile --background \ + --chuid $GROUP:$USER --pidfile $pidfile --background --no-close \ -- -pidfile $pidfile -config $config $INFLUXD_OPTS \ >>$STDOUT 2>>$STDERR diff -Nru influxdb-1.0.2+dfsg1/debian/patches/disable-reporting.patch influxdb-1.1.1+dfsg1/debian/patches/disable-reporting.patch --- influxdb-1.0.2+dfsg1/debian/patches/disable-reporting.patch 2016-10-25 17:19:04.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/patches/disable-reporting.patch 2016-12-22 05:50:08.000000000 +0000 @@ -42,7 +42,7 @@ httpAPIAddr: c.HTTPD.BindAddress, httpUseTLS: c.HTTPD.HTTPSEnabled, -@@ -441,7 +441,7 @@ +@@ -434,7 +434,7 @@ } // Start the reporting service, if not disabled. @@ -51,3 +51,14 @@ go s.startServerReporting() } +--- a/cmd/influxd/run/server_helpers_test.go ++++ b/cmd/influxd/run/server_helpers_test.go +@@ -229,7 +229,7 @@ + func NewConfig() *run.Config { + c := run.NewConfig() + c.BindAddress = "127.0.0.1:0" +- c.ReportingDisabled = true ++ c.ReportingEnabled = false + c.Coordinator.WriteTimeout = toml.Duration(30 * time.Second) + c.Meta.Dir = MustTempFile() + diff -Nru influxdb-1.0.2+dfsg1/debian/patches/jwt-v2.patch influxdb-1.1.1+dfsg1/debian/patches/jwt-v2.patch --- influxdb-1.0.2+dfsg1/debian/patches/jwt-v2.patch 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/patches/jwt-v2.patch 2016-12-22 05:50:08.000000000 +0000 @@ -0,0 +1,67 @@ +Description: Fix build with github.com/dgrijalva/jwt-go v2 +Author: Guillem Jover +Last-Update: 2016-12-02 + +--- + services/httpd/handler.go | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +--- a/services/httpd/handler.go ++++ b/services/httpd/handler.go +@@ -901,21 +901,14 @@ + return + } + +- claims, ok := token.Claims.(jwt.MapClaims) +- if !ok { +- h.httpError(w, "problem authenticating token", http.StatusInternalServerError) +- h.Logger.Print("Could not assert JWT token claims as jwt.MapClaims") +- return +- } +- + // Make sure an expiration was set on the token. +- if exp, ok := claims["exp"].(float64); !ok || exp <= 0.0 { ++ if exp, ok := token.Claims["exp"].(float64); !ok || exp <= 0.0 { + h.httpError(w, "token expiration required", http.StatusUnauthorized) + return + } + + // Get the username from the token. +- username, ok := claims["username"].(string) ++ username, ok := token.Claims["username"].(string) + if !ok { + h.httpError(w, "username in token must be a string", http.StatusUnauthorized) + return +--- a/services/httpd/handler_test.go ++++ b/services/httpd/handler_test.go +@@ -193,13 +193,13 @@ + h.ServeHTTP(w, req) + if w.Code != http.StatusUnauthorized { + t.Fatalf("unexpected status: %d: %s", w.Code, w.Body.String()) +- } else if !strings.Contains(w.Body.String(), `{"error":"Token is expired`) { ++ } else if !strings.Contains(w.Body.String(), `{"error":"token is expired`) { + t.Fatalf("unexpected body: %s", w.Body.String()) + } + + // Test handler with JWT token that has no expiration set. + token, _ := MustJWTToken("user1", h.Config.SharedSecret, false) +- delete(token.Claims.(jwt.MapClaims), "exp") ++ delete(token.Claims, "exp") + signedToken, err := token.SignedString([]byte(h.Config.SharedSecret)) + if err != nil { + t.Fatal(err) +@@ -707,11 +707,11 @@ + // MustJWTToken returns a new JWT token and signed string or panics trying. + func MustJWTToken(username, secret string, expired bool) (*jwt.Token, string) { + token := jwt.New(jwt.GetSigningMethod("HS512")) +- token.Claims.(jwt.MapClaims)["username"] = username ++ token.Claims["username"] = username + if expired { +- token.Claims.(jwt.MapClaims)["exp"] = time.Now().Add(-time.Second).Unix() ++ token.Claims["exp"] = time.Now().Add(-time.Second).Unix() + } else { +- token.Claims.(jwt.MapClaims)["exp"] = time.Now().Add(time.Minute * 10).Unix() ++ token.Claims["exp"] = time.Now().Add(time.Minute * 10).Unix() + } + signed, err := token.SignedString([]byte(secret)) + if err != nil { diff -Nru influxdb-1.0.2+dfsg1/debian/patches/series influxdb-1.1.1+dfsg1/debian/patches/series --- influxdb-1.0.2+dfsg1/debian/patches/series 2016-10-25 17:19:04.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/patches/series 2016-12-22 05:50:08.000000000 +0000 @@ -1 +1,2 @@ disable-reporting.patch +jwt-v2.patch diff -Nru influxdb-1.0.2+dfsg1/debian/rules influxdb-1.1.1+dfsg1/debian/rules --- influxdb-1.0.2+dfsg1/debian/rules 2016-10-25 17:19:04.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/rules 2016-12-22 05:50:08.000000000 +0000 @@ -16,6 +16,9 @@ # Include tests files cp -v $(SOURCE)/stress/stress.toml _build/src/$(DH_GOPKG)/stress/stress.toml + mkdir -v -p _build/src/$(DH_GOPKG)/stress/v2/iql + cp -v $(SOURCE)/stress/v2/iql/file.iql _build/src/$(DH_GOPKG)/stress/v2/iql/file.iql + cp -v $(SOURCE)/stress/v2/iql/default.iql _build/src/$(DH_GOPKG)/stress/v2/iql/default.iql # Install Web UI components cp -v -r $(SOURCE)/services/admin/assets _build/src/$(DH_GOPKG)/services/admin @@ -49,17 +52,15 @@ dh_auto_build -- -ldflags="-X main.version=$(DEB_UPSTREAM_VERSION)" # Don't tests on unsupported architectures. Test are unstable. -# See issue: https://github.com/influxdata/influxdb/issues/4102 -# In the future, we should only skip cluster tests. SKIP_TESTS := True -#ifeq ($(DEB_HOST_ARCH_CPU),amd64) -#SKIP_TESTS := False -#endif - -#ifeq ($(DEB_HOST_ARCH_CPU),i386) -#SKIP_TESTS := False -#endif +ifeq ($(DEB_HOST_ARCH_CPU),amd64) +SKIP_TESTS := False +endif + +ifeq ($(DEB_HOST_ARCH_CPU),i386) +SKIP_TESTS := False +endif override_dh_auto_test: if [ "$(SKIP_TESTS)" = "True" ]; then \ diff -Nru influxdb-1.0.2+dfsg1/debian/source/lintian-overrides influxdb-1.1.1+dfsg1/debian/source/lintian-overrides --- influxdb-1.0.2+dfsg1/debian/source/lintian-overrides 2016-10-25 17:19:04.000000000 +0000 +++ influxdb-1.1.1+dfsg1/debian/source/lintian-overrides 2016-12-22 05:50:08.000000000 +0000 @@ -1,3 +1,3 @@ # False positive, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=799861 -source-contains-prebuilt-javascript-object debian/missing-sources/react-0.13.3.js -source-is-missing debian/missing-sources/react-0.13.3.js +source-contains-prebuilt-javascript-object debian/missing-sources/react-0.13.3.js * +source-is-missing debian/missing-sources/react-0.13.3.js * diff -Nru influxdb-1.0.2+dfsg1/Dockerfile_build_ubuntu32 influxdb-1.1.1+dfsg1/Dockerfile_build_ubuntu32 --- influxdb-1.0.2+dfsg1/Dockerfile_build_ubuntu32 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/Dockerfile_build_ubuntu32 2016-12-06 21:36:15.000000000 +0000 @@ -18,7 +18,7 @@ # Install go ENV GOPATH /root/go -ENV GO_VERSION 1.6.2 +ENV GO_VERSION 1.7.4 ENV GO_ARCH 386 RUN wget https://storage.googleapis.com/golang/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz; \ tar -C /usr/local/ -xf /go${GO_VERSION}.linux-${GO_ARCH}.tar.gz ; \ diff -Nru influxdb-1.0.2+dfsg1/Dockerfile_build_ubuntu64 influxdb-1.1.1+dfsg1/Dockerfile_build_ubuntu64 --- influxdb-1.0.2+dfsg1/Dockerfile_build_ubuntu64 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/Dockerfile_build_ubuntu64 2016-12-06 21:36:15.000000000 +0000 @@ -21,7 +21,7 @@ # Install go ENV GOPATH /root/go -ENV GO_VERSION 1.6.2 +ENV GO_VERSION 1.7.4 ENV GO_ARCH amd64 RUN wget https://storage.googleapis.com/golang/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz; \ tar -C /usr/local/ -xf /go${GO_VERSION}.linux-${GO_ARCH}.tar.gz ; \ diff -Nru influxdb-1.0.2+dfsg1/Dockerfile_build_ubuntu64_git influxdb-1.1.1+dfsg1/Dockerfile_build_ubuntu64_git --- influxdb-1.0.2+dfsg1/Dockerfile_build_ubuntu64_git 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/Dockerfile_build_ubuntu64_git 2016-12-06 21:36:15.000000000 +0000 @@ -26,7 +26,7 @@ # Install go -ENV GO_VERSION 1.6.2 +ENV GO_VERSION 1.7.4 ENV GO_ARCH amd64 RUN wget https://storage.googleapis.com/golang/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz; \ tar -C /usr/local/ -xf /go${GO_VERSION}.linux-${GO_ARCH}.tar.gz ; \ diff -Nru influxdb-1.0.2+dfsg1/DOCKER.md influxdb-1.1.1+dfsg1/DOCKER.md --- influxdb-1.0.2+dfsg1/DOCKER.md 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/DOCKER.md 2016-12-06 21:36:15.000000000 +0000 @@ -11,12 +11,12 @@ $ ./build-docker.sh ``` -This script uses the `golang:1.5` image to build a fully static binary of `influxd` and then adds it to a minimal `scratch` image. +This script uses the `golang:1.7.4` image to build a fully static binary of `influxd` and then adds it to a minimal `scratch` image. To build the image using a different version of go: ``` -$ GO_VER=1.4.2 ./build-docker.sh +$ GO_VER=1.7.4 ./build-docker.sh ``` Available version can be found [here](https://hub.docker.com/_/golang/). diff -Nru influxdb-1.0.2+dfsg1/errors.go influxdb-1.1.1+dfsg1/errors.go --- influxdb-1.0.2+dfsg1/errors.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/errors.go 2016-12-06 21:36:15.000000000 +0000 @@ -6,18 +6,9 @@ "strings" ) -var ( - // ErrFieldsRequired is returned when a point does not any fields. - ErrFieldsRequired = errors.New("fields required") - - // ErrFieldTypeConflict is returned when a new field already exists with a different type. - ErrFieldTypeConflict = errors.New("field type conflict") - - // ErrUpgradeEngine will be returned when it's determined that - // the server has encountered shards that are not in the `tsm1` - // format. - ErrUpgradeEngine = errors.New("\n\n" + upgradeMessage + "\n\n") -) +// ErrFieldTypeConflict is returned when a new field already exists with a +// different type. +var ErrFieldTypeConflict = errors.New("field type conflict") // ErrDatabaseNotFound indicates that a database operation failed on the // specified database because the specified database does not exist. @@ -35,14 +26,7 @@ return false } - if err == ErrFieldsRequired { - return true - } - if err == ErrFieldTypeConflict { - return true - } - - if strings.Contains(err.Error(), ErrFieldTypeConflict.Error()) { + if strings.HasPrefix(err.Error(), ErrFieldTypeConflict.Error()) { return true } diff -Nru influxdb-1.0.2+dfsg1/etc/config.sample.toml influxdb-1.1.1+dfsg1/etc/config.sample.toml --- influxdb-1.0.2+dfsg1/etc/config.sample.toml 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/etc/config.sample.toml 2016-12-06 21:36:15.000000000 +0000 @@ -1,10 +1,15 @@ ### Welcome to the InfluxDB configuration file. +# The values in this file override the default values used by the system if +# a config option is not specified. The commented out lines are the the configuration +# field and the default value used. Uncommentting a line and changing the value +# will change the value used at runtime when the process is restarted. + # Once every 24 hours InfluxDB will report usage data to usage.influxdata.com # The data includes a random ID, os, arch, version, the number of series and other # usage data. No data from user databases is ever transmitted. # Change this option to true to disable reporting. -reporting-disabled = false +# reporting-disabled = false # we'll try to get the hostname automatically, but if it the os returns something # that isn't resolvable by other servers in the cluster, use this option to @@ -22,14 +27,11 @@ # Where the metadata/raft database is stored dir = "/var/lib/influxdb/meta" - retention-autocreate = true + # Automatically create a default retention policy when creating a database. + # retention-autocreate = true # If log messages are printed for the meta service - logging-enabled = true - pprof-enabled = false - - # The default duration for leases. - lease-duration = "1m0s" + # logging-enabled = true ### ### [data] @@ -41,14 +43,11 @@ ### [data] - # Controls if this node holds time series data shards in the cluster - enabled = true - + # The directory where the TSM storage engine stores TSM files. dir = "/var/lib/influxdb/data" - # These are the WAL settings for the storage engine >= 0.9.3 + # The directory where the TSM storage engine stores WAL files. wal-dir = "/var/lib/influxdb/wal" - wal-logging-enabled = true # Trace logging provides more verbose output around the tsm engine. Turning # this on can provide more useful output for debugging tsm engine issues. @@ -62,7 +61,7 @@ # CacheMaxMemorySize is the maximum size a shard's cache can # reach before it starts rejecting writes. - # cache-max-memory-size = 524288000 + # cache-max-memory-size = 1048576000 # CacheSnapshotMemorySize is the size at which the engine will # snapshot the cache and write it to a TSM file, freeing up memory @@ -71,21 +70,22 @@ # CacheSnapshotWriteColdDuration is the length of time at # which the engine will snapshot the cache and write it to # a new TSM file if the shard hasn't received writes or deletes - # cache-snapshot-write-cold-duration = "1h" - - # MinCompactionFileCount is the minimum number of TSM files - # that need to exist before a compaction cycle will run - # compact-min-file-count = 3 + # cache-snapshot-write-cold-duration = "10m" # CompactFullWriteColdDuration is the duration at which the engine # will compact all TSM files in a shard if it hasn't received a # write or delete - # compact-full-write-cold-duration = "24h" + # compact-full-write-cold-duration = "4h" - # MaxPointsPerBlock is the maximum number of points in an encoded - # block in a TSM file. Larger numbers may yield better compression - # but could incur a performance penalty when querying - # max-points-per-block = 1000 + # The maximum series allowed per database before writes are dropped. This limit can prevent + # high cardinality issues at the database level. This limit can be disabled by setting it to + # 0. + # max-series-per-database = 1000000 + + # The maximum number of tag values per tag that are allowed before writes are dropped. This limit + # can prevent high cardinality tag values from being written to a measurement. This limit can be + # disabled by setting it to 0. + # max-values-per-tag = 100000 ### ### [coordinator] @@ -93,14 +93,37 @@ ### Controls the clustering service configuration. ### -[coordinator] - write-timeout = "10s" - max-concurrent-queries = 0 - query-timeout = "0" - log-queries-after = "0" - max-select-point = 0 - max-select-series = 0 - max-select-buckets = 0 +# [coordinator] + # The default time a write request will wait until a "timeout" error is returned to the caller. + # write-timeout = "10s" + + # The maximum number of concurrent queries allowed to be executing at one time. If a query is + # executed and exceeds this limit, an error is returned to the caller. This limit can be disabled + # by setting it to 0. + # max-concurrent-queries = 0 + + # The maximum time a query will is allowed to execute before being killed by the system. This limit + # can help prevent run away queries. Setting the value to 0 disables the limit. + # query-timeout = "0s" + + # The the time threshold when a query will be logged as a slow query. This limit can be set to help + # discover slow or resource intensive queries. Setting the value to 0 disables the slow query logging. + # log-queries-after = "0s" + + # The maximum number of points a SELECT can process. A value of 0 will make the maximum + # point count unlimited. + # max-select-point = 0 + + # The maximum number of series a SELECT can run. A value of 0 will make the maximum series + # count unlimited. + + # The maximum number of series a SELECT can run. A value of zero will make the maximum series + # count unlimited. + # max-select-series = 0 + + # The maxium number of group by time bucket a SELECt can create. A value of zero will max the maximum + # number of buckets unlimited. + # max-select-buckets = 0 ### ### [retention] @@ -108,9 +131,12 @@ ### Controls the enforcement of retention policies for evicting old data. ### -[retention] - enabled = true - check-interval = "30m" +# [retention] + # Determines whether retention policy enforcment enabled. + # enabled = true + + # The interval of time when retention policy enforcement checks run. + # check-interval = "30m" ### ### [shard-precreation] @@ -120,10 +146,16 @@ ### future, will ever be created. Shards are never precreated that would be wholly ### or partially in the past. -[shard-precreation] - enabled = true - check-interval = "10m" - advance-period = "30m" +# [shard-precreation] + # Determines whether shard pre-creation service is enabled. + # enabled = true + + # The interval of time when the check to pre-create new shards runs. + # check-interval = "10m" + + # The default period ahead of the endtime of a shard group that its successor + # group is created. + # advance-period = "30m" ### ### Controls the system self-monitoring, statistics and diagnostics. @@ -134,10 +166,15 @@ ### and a replication factor of 1, if it does not exist. In all cases the ### this retention policy is configured as the default for the database. -[monitor] - store-enabled = true # Whether to record statistics internally. - store-database = "_internal" # The destination database for recorded statistics - store-interval = "10s" # The interval at which to record statistics +# [monitor] + # Whether to record statistics internally. + # store-enabled = true + + # The destination database for recorded statistics + # store-database = "_internal" + + # The interval at which to record statistics + # store-interval = "10s" ### ### [admin] @@ -145,12 +182,20 @@ ### Controls the availability of the built-in, web-based admin interface. If HTTPS is ### enabled for the admin interface, HTTPS must also be enabled on the [http] service. ### +### NOTE: This interface is deprecated as of 1.1.0 and will be removed in a future release. + +# [admin] + # Determines whether the admin service is enabled. + # enabled = false + + # The default bind address used by the admin service. + # bind-address = ":8083" -[admin] - enabled = true - bind-address = ":8083" - https-enabled = false - https-certificate = "/etc/ssl/influxdb.pem" + # Whether the admin service should use HTTPS. + # https-enabled = false + + # The SSL certificate used when HTTPS is enabled. + # https-certificate = "/etc/ssl/influxdb.pem" ### ### [http] @@ -159,19 +204,53 @@ ### mechanism for getting data into and out of InfluxDB. ### -[http] - enabled = true - bind-address = ":8086" - auth-enabled = false - log-enabled = true - write-tracing = false - pprof-enabled = false - https-enabled = false - https-certificate = "/etc/ssl/influxdb.pem" - ### Use a separate private key location. +# [http] + # Determines whether HTTP endpoint is enabled. + # enabled = true + + # The bind address used by the HTTP service. + # bind-address = ":8086" + + # Determines whether HTTP authentication is enabled. + # auth-enabled = false + + # The default realm sent back when issuing a basic auth challenge. + # realm = "InfluxDB" + + # Determines whether HTTP request logging is enable.d + # log-enabled = true + + # Determines whether detailed write logging is enabled. + # write-tracing = false + + # Determines whether the pprof endpoint is enabled. This endpoint is used for + # troubleshooting and monitoring. + # pprof-enabled = true + + # Determines whether HTTPS is enabled. + # https-enabled = false + + # The SSL certificate to use when HTTPS is enabled. + # https-certificate = "/etc/ssl/influxdb.pem" + + # Use a separate private key location. # https-private-key = "" - max-row-limit = 10000 - realm = "InfluxDB" + + # The JWT auth shared secret to validate requests using JSON web tokens. + # shared-sercret = "" + + # The default chunk size for result sets that should be chunked. + # max-row-limit = 10000 + + # The maximum number of HTTP connections that may be open at once. New connections that + # would exceed this limit are dropped. Setting this value to 0 disables the limit. + # max-connection-limit = 0 + + # Enable http service over unix domain socket + # unix-socket-enabled = false + + # The path of the unix domain socket. + # bind-socket = "/var/run/influxdb.sock" ### ### [subscriber] @@ -180,10 +259,24 @@ ### received by the InfluxDB host. ### -[subscriber] - enabled = true +# [subscriber] + # Determines whether the subscriber service is enabled. + # enabled = true + + # The default timeout for HTTP writes to subscribers. # http-timeout = "30s" + + # Allows insecure HTTPS connections to subscribers. This is useful when testing with self- + # signed certificates. + # insecure-skip-verify = false + + # The path to the PEM encoded CA certs file. If the empty string, the default system certs will be used + # ca-certs = "" + + # The number of writer goroutines processing the write channel. # write-concurrency = 40 + + # The number of in-flight writes buffered in the write channel. # write-buffer-size = 1000 @@ -193,9 +286,11 @@ ### Controls one or many listeners for Graphite data. ### -[[graphite]] - enabled = false +# [[graphite]] + # Determines whether the graphite endpoint is enabled. + # enabled = false # database = "graphite" + # retention-policy = "" # bind-address = ":2003" # protocol = "tcp" # consistency-level = "one" @@ -204,10 +299,17 @@ # otherwise you could get dropped metrics or poor performance. Batching # will buffer points in memory if you have many coming in. - # batch-size = 5000 # will flush if this many points get buffered - # batch-pending = 10 # number of batches that may be pending in memory - # batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit - # udp-read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # Flush if this many points get buffered + # batch-size = 5000 + + # number of batches that may be pending in memory + # batch-pending = 10 + + # Flush at least this often even if we haven't hit buffer limit + # batch-timeout = "1s" + + # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # udp-read-buffer = 0 ### This string joins multiple matching 'measurement' values providing more control over the final measurement name. # separator = "." @@ -232,20 +334,28 @@ ### Controls one or many listeners for collectd data. ### -[[collectd]] - enabled = false - # bind-address = "" - # database = "" - # typesdb = "" +# [[collectd]] + # enabled = false + # bind-address = ":25826" + # database = "collectd" + # retention-policy = "" + # typesdb = "/usr/share/collectd/types.db" # These next lines control how batching works. You should have this enabled # otherwise you could get dropped metrics or poor performance. Batching # will buffer points in memory if you have many coming in. - # batch-size = 1000 # will flush if this many points get buffered - # batch-pending = 5 # number of batches that may be pending in memory - # batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit - # read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # Flush if this many points get buffered + # batch-size = 5000 + + # Number of batches that may be pending in memory + # batch-pending = 10 + + # Flush at least this often even if we haven't hit buffer limit + # batch-timeout = "10s" + + # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # read-buffer = 0 ### ### [opentsdb] @@ -253,23 +363,30 @@ ### Controls one or many listeners for OpenTSDB data. ### -[[opentsdb]] - enabled = false +# [[opentsdb]] + # enabled = false # bind-address = ":4242" # database = "opentsdb" # retention-policy = "" # consistency-level = "one" # tls-enabled = false - # certificate= "" - # log-point-errors = true # Log an error for every malformed point. + # certificate= "/etc/ssl/influxdb.pem" + + # Log an error for every malformed point. + # log-point-errors = true # These next lines control how batching works. You should have this enabled # otherwise you could get dropped metrics or poor performance. Only points # metrics received over the telnet protocol undergo batching. - # batch-size = 1000 # will flush if this many points get buffered - # batch-pending = 5 # number of batches that may be pending in memory - # batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit + # Flush if this many points get buffered + # batch-size = 1000 + + # Number of batches that may be pending in memory + # batch-pending = 5 + + # Flush at least this often even if we haven't hit buffer limit + # batch-timeout = "1s" ### ### [[udp]] @@ -277,9 +394,9 @@ ### Controls the listeners for InfluxDB line protocol data via UDP. ### -[[udp]] - enabled = false - # bind-address = "" +# [[udp]] + # enabled = false + # bind-address = ":8089" # database = "udp" # retention-policy = "" @@ -287,13 +404,17 @@ # otherwise you could get dropped metrics or poor performance. Batching # will buffer points in memory if you have many coming in. - # batch-size = 1000 # will flush if this many points get buffered - # batch-pending = 5 # number of batches that may be pending in memory - # batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit - # read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # Flush if this many points get buffered + # batch-size = 5000 + + # Number of batches that may be pending in memory + # batch-pending = 10 + + # Will flush at least this often even if we haven't hit buffer limit + # batch-timeout = "1s" - # set the expected UDP payload size; lower values tend to yield better performance, default is max UDP size 65536 - # udp-payload-size = 65536 + # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max. + # read-buffer = 0 ### ### [continuous_queries] @@ -301,7 +422,12 @@ ### Controls how continuous queries are run within InfluxDB. ### -[continuous_queries] - log-enabled = true - enabled = true - # run-interval = "1s" # interval for how often continuous queries will be checked if they need to run +# [continuous_queries] + # Determiens whether the continuous query service is enabled. + # enabled = true + + # Controls whether queries are logged when executed by the CQ service. + # log-enabled = true + + # interval for how often continuous queries will be checked if they need to run + # run-interval = "1s" diff -Nru influxdb-1.0.2+dfsg1/.gitignore influxdb-1.1.1+dfsg1/.gitignore --- influxdb-1.0.2+dfsg1/.gitignore 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/.gitignore 2016-12-06 21:36:15.000000000 +0000 @@ -1,23 +1,21 @@ +# Keep editor-specific, non-project specific ignore rules in global .gitignore: +# https://help.github.com/articles/ignoring-files/#create-a-global-gitignore + *~ src/ config.json /bin/ -TAGS - -# vim temp files -*.swp - -*.test /query/a.out* -.DS_Store # ignore generated files. cmd/influxd/version.go # executables +*.test + influx_tsm **/influx_tsm !**/influx_tsm/ @@ -69,15 +67,6 @@ # test data files integration/migration_data/ -# goide project files -.idea - -# goconvey config files -*.goconvey - -// Ingnore SourceGraph directory -.srclib-store/ - # man outputs man/*.xml man/*.1 diff -Nru influxdb-1.0.2+dfsg1/Godeps influxdb-1.1.1+dfsg1/Godeps --- influxdb-1.0.2+dfsg1/Godeps 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/Godeps 2016-12-06 21:36:15.000000000 +0000 @@ -3,13 +3,13 @@ github.com/bmizerany/pat c068ca2f0aacee5ac3681d68e4d0a003b7d1fd2c github.com/boltdb/bolt 5cc10bbbc5c141029940133bb33c9e969512a698 github.com/davecgh/go-spew 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d -github.com/dgrijalva/jwt-go 9b486c879bab3fde556ce8c27d9a2bb05d5b2c60 +github.com/dgrijalva/jwt-go 63734eae1ef55eaac06fdc0f312615f2e321e273 github.com/dgryski/go-bits 2ad8d707cc05b1815ce6ff2543bb5e8d8f9298ef github.com/dgryski/go-bitstream 7d46cd22db7004f0cceb6f7975824b560cf0e486 -github.com/gogo/protobuf 6abcf94fd4c97dcb423fdafd42fe9f96ca7e421b +github.com/gogo/protobuf 0394392b81058a7f972029451f06e528bb18ba50 github.com/golang/snappy d9eb7a3d35ec988b8585d4a0068e462c27d28380 -github.com/influxdata/usage-client 475977e68d79883d9c8d67131c84e4241523f452 -github.com/jwilder/encoding ac74639f65b2180a2e5eb5ff197f0c122441aed0 +github.com/influxdata/usage-client 6d3895376368aa52a3a81d2a16e90f0f52371967 +github.com/jwilder/encoding 4dada27c33277820fe35c7ee71ed34fbc9477d00 github.com/kimor79/gollectd 61d0deeb4ffcc167b2a1baa8efd72365692811bc github.com/paulbellamy/ratecounter 5a11f585a31379765c190c033b6ad39956584447 github.com/peterh/liner 8975875355a81d612fafb9f5a6037bdcc2d9b073 diff -Nru influxdb-1.0.2+dfsg1/influxql/ast.go influxdb-1.1.1+dfsg1/influxql/ast.go --- influxdb-1.0.2+dfsg1/influxql/ast.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/ast.go 2016-12-06 21:36:15.000000000 +0000 @@ -5,6 +5,7 @@ "errors" "fmt" "regexp" + "regexp/syntax" "sort" "strconv" "strings" @@ -892,6 +893,8 @@ NumberFill // PreviousFill means that empty aggregate windows will be filled with whatever the previous aggregate window had PreviousFill + // LinearFill means that empty aggregate windows will be filled with whatever a linear value between non null windows + LinearFill ) // SelectStatement represents a command for extracting data from the database. @@ -1126,6 +1129,12 @@ } rwFields = append(rwFields, &Field{Expr: &VarRef{Val: ref.Val, Type: ref.Type}}) } + case *RegexLiteral: + for _, ref := range fields { + if expr.Val.MatchString(ref.Val) { + rwFields = append(rwFields, &Field{Expr: &VarRef{Val: ref.Val, Type: ref.Type}}) + } + } case *Call: // Clone a template that we can modify and use for new fields. template := CloneExpr(expr).(*Call) @@ -1147,10 +1156,16 @@ continue } - wc, ok := call.Args[0].(*Wildcard) - if ok && wc.Type == TAG { - return s, fmt.Errorf("unable to use tag wildcard in %s()", call.Name) - } else if !ok { + // Retrieve if this is a wildcard or a regular expression. + var re *regexp.Regexp + switch expr := call.Args[0].(type) { + case *Wildcard: + if expr.Type == TAG { + return s, fmt.Errorf("unable to use tag wildcard in %s()", call.Name) + } + case *RegexLiteral: + re = expr.Val + default: rwFields = append(rwFields, f) continue } @@ -1165,9 +1180,7 @@ switch call.Name { case "count", "first", "last", "distinct", "elapsed", "mode": supportedTypes[String] = struct{}{} - supportedTypes[Boolean] = struct{}{} - case "stddev": - supportedTypes[String] = struct{}{} + fallthrough case "min", "max": supportedTypes[Boolean] = struct{}{} } @@ -1179,6 +1192,8 @@ continue } else if _, ok := supportedTypes[ref.Type]; !ok { continue + } else if re != nil && !re.MatchString(ref.Val) { + continue } // Make a new expression and replace the wildcard within this cloned expression. @@ -1200,11 +1215,17 @@ // Allocate a slice assuming there is exactly one wildcard for efficiency. rwDimensions := make(Dimensions, 0, len(s.Dimensions)+len(dimensions)-1) for _, d := range s.Dimensions { - switch d.Expr.(type) { + switch expr := d.Expr.(type) { case *Wildcard: for _, name := range dimensions { rwDimensions = append(rwDimensions, &Dimension{Expr: &VarRef{Val: name}}) } + case *RegexLiteral: + for _, name := range dimensions { + if expr.Val.MatchString(name) { + rwDimensions = append(rwDimensions, &Dimension{Expr: &VarRef{Val: name}}) + } + } default: rwDimensions = append(rwDimensions, d) } @@ -1215,6 +1236,93 @@ return other, nil } +// RewriteRegexExprs rewrites regex conditions to make better use of the +// database index. +// +// Conditions that can currently be simplified are: +// +// - host =~ /^foo$/ becomes host = 'foo' +// - host !~ /^foo$/ becomes host != 'foo' +// +// Note: if the regex contains groups, character classes, repetition or +// similar, it's likely it won't be rewritten. In order to support rewriting +// regexes with these characters would be a lot more work. +func (s *SelectStatement) RewriteRegexConditions() { + s.Condition = RewriteExpr(s.Condition, func(e Expr) Expr { + be, ok := e.(*BinaryExpr) + if !ok || (be.Op != EQREGEX && be.Op != NEQREGEX) { + // This expression is not a binary condition or doesn't have a + // regex based operator. + return e + } + + // Handle regex-based condition. + rhs := be.RHS.(*RegexLiteral) // This must be a regex. + + val, ok := matchExactRegex(rhs.Val.String()) + if !ok { + // Regex didn't match. + return e + } + + // Remove leading and trailing ^ and $. + be.RHS = &StringLiteral{Val: val} + + // Update the condition operator. + if be.Op == EQREGEX { + be.Op = EQ + } else { + be.Op = NEQ + } + return be + }) +} + +// matchExactRegex matches regexes that have the following form: /^foo$/. It +// considers /^$/ to be a matching regex. +func matchExactRegex(v string) (string, bool) { + re, err := syntax.Parse(v, syntax.Perl) + if err != nil { + // Nothing we can do or log. + return "", false + } + + if re.Op != syntax.OpConcat { + return "", false + } + + if len(re.Sub) < 2 || len(re.Sub) > 3 { + // Regex has too few or too many subexpressions. + return "", false + } + + start := re.Sub[0] + if !(start.Op == syntax.OpBeginLine || start.Op == syntax.OpBeginText) { + // Regex does not begin with ^ + return "", false + } + + end := re.Sub[len(re.Sub)-1] + if !(end.Op == syntax.OpEndLine || end.Op == syntax.OpEndText) { + // Regex does not end with $ + return "", false + } + + if len(re.Sub) == 3 { + middle := re.Sub[1] + if middle.Op != syntax.OpLiteral { + // Regex does not contain a literal op. + return "", false + } + + // We can rewrite this regex. + return string(middle.Rune), true + } + + // The regex /^$/ + return "", true +} + // RewriteDistinct rewrites the expression to be a call for map/reduce to work correctly // This method assumes all validation has passed func (s *SelectStatement) RewriteDistinct() { @@ -1356,6 +1464,8 @@ _, _ = buf.WriteString(" fill(none)") case NumberFill: _, _ = buf.WriteString(fmt.Sprintf(" fill(%v)", s.FillValue)) + case LinearFill: + _, _ = buf.WriteString(" fill(linear)") case PreviousFill: _, _ = buf.WriteString(" fill(previous)") } @@ -1416,8 +1526,8 @@ if hasWildcard { return } - _, ok := n.(*Wildcard) - if ok { + switch n.(type) { + case *Wildcard, *RegexLiteral: hasWildcard = true } }) @@ -1428,8 +1538,8 @@ // at least 1 wildcard in the dimensions aka `GROUP BY` func (s *SelectStatement) HasDimensionWildcard() bool { for _, d := range s.Dimensions { - _, ok := d.Expr.(*Wildcard) - if ok { + switch d.Expr.(type) { + case *Wildcard, *RegexLiteral: return true } } @@ -1511,6 +1621,7 @@ return errors.New("time() is a function and expects at least one argument") } case *Wildcard: + case *RegexLiteral: default: return errors.New("only time and tag dimensions allowed") } @@ -1540,7 +1651,7 @@ onlySelectors := true for k := range calls { switch k { - case "top", "bottom", "max", "min", "first", "last", "percentile": + case "top", "bottom", "max", "min", "first", "last", "percentile", "sample": default: onlySelectors = false break @@ -1597,7 +1708,7 @@ } switch expr.Args[0].(type) { - case *VarRef: + case *VarRef, *RegexLiteral, *Wildcard: // do nothing default: return fmt.Errorf("expected field argument in percentile()") @@ -1611,20 +1722,40 @@ } } +// validPercentileAggr determines if PERCENTILE have valid arguments. +func (s *SelectStatement) validSampleAggr(expr *Call) error { + if err := s.validSelectWithAggregate(); err != nil { + return err + } + if exp, got := 2, len(expr.Args); got != exp { + return fmt.Errorf("invalid number of arguments for %s, expected %d, got %d", expr.Name, exp, got) + } + + switch expr.Args[0].(type) { + case *VarRef, *RegexLiteral, *Wildcard: + // do nothing + default: + return fmt.Errorf("expected field argument in sample()") + } + + switch expr.Args[1].(type) { + case *IntegerLiteral: + return nil + default: + return fmt.Errorf("expected integer argument in sample()") + } +} + func (s *SelectStatement) validateAggregates(tr targetRequirement) error { for _, f := range s.Fields { for _, expr := range walkFunctionCalls(f.Expr) { switch expr.Name { - case "derivative", "non_negative_derivative", "difference", "moving_average", "elapsed": + case "derivative", "non_negative_derivative", "difference", "moving_average", "cumulative_sum", "elapsed": if err := s.validSelectWithAggregate(); err != nil { return err } switch expr.Name { - case "derivative", "non_negative_derivative": - if min, max, got := 1, 2, len(expr.Args); got > max || got < min { - return fmt.Errorf("invalid number of arguments for %s, expected at least %d but no more than %d, got %d", expr.Name, min, max, got) - } - case "elapsed": + case "derivative", "non_negative_derivative", "elapsed": if min, max, got := 1, 2, len(expr.Args); got > max || got < min { return fmt.Errorf("invalid number of arguments for %s, expected at least %d but no more than %d, got %d", expr.Name, min, max, got) } @@ -1632,12 +1763,12 @@ if len(expr.Args) == 2 { // Second must be a duration .e.g (1h) if _, ok := expr.Args[1].(*DurationLiteral); !ok { - return errors.New("elapsed requires a duration argument") + return fmt.Errorf("second argument to %s must be a duration, got %T", expr.Name, expr.Args[1]) } } - case "difference": + case "difference", "cumulative_sum": if got := len(expr.Args); got != 1 { - return fmt.Errorf("invalid number of arguments for difference, expected 1, got %d", got) + return fmt.Errorf("invalid number of arguments for %s, expected 1, got %d", expr.Name, got) } case "moving_average": if got := len(expr.Args); got != 2 { @@ -1678,7 +1809,7 @@ } switch fc := c.Args[0].(type) { - case *VarRef, *Wildcard: + case *VarRef, *Wildcard, *RegexLiteral: // do nothing case *Call: if fc.Name != "distinct" || expr.Name != "count" { @@ -1705,6 +1836,10 @@ if err := s.validPercentileAggr(expr); err != nil { return err } + case "sample": + if err := s.validSampleAggr(expr); err != nil { + return err + } case "holt_winters", "holt_winters_with_fit": if exp, got := 3, len(expr.Args); got != exp { return fmt.Errorf("invalid number of arguments for %s, expected %d, got %d", expr.Name, exp, got) @@ -1742,7 +1877,7 @@ return fmt.Errorf("invalid number of arguments for %s, expected %d, got %d", expr.Name, exp, got) } switch fc := expr.Args[0].(type) { - case *VarRef, *Wildcard: + case *VarRef, *Wildcard, *RegexLiteral: // do nothing case *Call: if fc.Name != "distinct" || expr.Name != "count" { @@ -1920,71 +2055,6 @@ return n.String() } -/* - -BinaryExpr - -SELECT mean(xxx.value) + avg(yyy.value) FROM xxx JOIN yyy WHERE xxx.host = 123 - -from xxx where host = 123 -select avg(value) from yyy where host = 123 - -SELECT xxx.value FROM xxx WHERE xxx.host = 123 -SELECT yyy.value FROM yyy - ---- - -SELECT MEAN(xxx.value) + MEAN(cpu.load.value) -FROM xxx JOIN yyy -GROUP BY host -WHERE (xxx.region == "uswest" OR yyy.region == "uswest") AND xxx.otherfield == "XXX" - -select * from ( - select mean + mean from xxx join yyy - group by time(5m), host -) (xxx.region == "uswest" OR yyy.region == "uswest") AND xxx.otherfield == "XXX" - -(seriesIDS for xxx.region = 'uswest' union seriesIDs for yyy.regnion = 'uswest') | seriesIDS xxx.otherfield = 'XXX' - -WHERE xxx.region == "uswest" AND xxx.otherfield == "XXX" -WHERE yyy.region == "uswest" - - -*/ - -// Substatement returns a single-series statement for a given variable reference. -func (s *SelectStatement) Substatement(ref *VarRef) (*SelectStatement, error) { - // Copy dimensions and properties to new statement. - other := &SelectStatement{ - Fields: Fields{{Expr: ref}}, - Dimensions: s.Dimensions, - Limit: s.Limit, - Offset: s.Offset, - SortFields: s.SortFields, - } - - // If there is only one series source then return it with the whole condition. - if len(s.Sources) == 1 { - other.Sources = s.Sources - other.Condition = s.Condition - return other, nil - } - - // Find the matching source. - name := MatchSource(s.Sources, ref.Val) - if name == "" { - return nil, fmt.Errorf("field source not found: %s", ref.Val) - } - other.Sources = append(other.Sources, &Measurement{Name: name}) - - // Filter out conditions. - if s.Condition != nil { - other.Condition = filterExprBySource(name, s.Condition) - } - - return other, nil -} - // NamesInWhere returns the field and tag names (idents) referenced in the where clause func (s *SelectStatement) NamesInWhere() []string { var a []string @@ -2066,7 +2136,7 @@ case *VarRef: return []VarRef{*expr} case *Call: - var a []VarRef + a := make([]VarRef, 0, len(expr.Args)) for _, expr := range expr.Args { if ref, ok := expr.(*VarRef); ok { a = append(a, *ref) @@ -2074,9 +2144,11 @@ } return a case *BinaryExpr: - var ret []VarRef - ret = append(ret, walkRefs(expr.LHS)...) - ret = append(ret, walkRefs(expr.RHS)...) + lhs := walkRefs(expr.LHS) + rhs := walkRefs(expr.RHS) + ret := make([]VarRef, 0, len(lhs)+len(rhs)) + ret = append(ret, lhs...) + ret = append(ret, rhs...) return ret case *ParenExpr: return walkRefs(expr.Expr) @@ -2244,6 +2316,10 @@ // ShowSeriesStatement represents a command for listing series in the database. type ShowSeriesStatement struct { + // Database to query. If blank, use the default database. + // The database can also be specified per source in the Sources. + Database string + // Measurement(s) the series are listed for. Sources Sources @@ -2266,6 +2342,10 @@ var buf bytes.Buffer _, _ = buf.WriteString("SHOW SERIES") + if s.Database != "" { + _, _ = buf.WriteString(" ON ") + _, _ = buf.WriteString(QuoteIdent(s.Database)) + } if s.Sources != nil { _, _ = buf.WriteString(" FROM ") _, _ = buf.WriteString(s.Sources.String()) @@ -2517,6 +2597,9 @@ // ShowMeasurementsStatement represents a command for listing measurements. type ShowMeasurementsStatement struct { + // Database to query. If blank, use the default database. + Database string + // Measurement name or regex. Source Source @@ -2539,6 +2622,10 @@ var buf bytes.Buffer _, _ = buf.WriteString("SHOW MEASUREMENTS") + if s.Database != "" { + _, _ = buf.WriteString(" ON ") + _, _ = buf.WriteString(s.Database) + } if s.Source != nil { _, _ = buf.WriteString(" WITH MEASUREMENT ") if m, ok := s.Source.(*Measurement); ok && m.Regex != nil { @@ -2613,8 +2700,11 @@ // String returns a string representation of a ShowRetentionPoliciesStatement. func (s *ShowRetentionPoliciesStatement) String() string { var buf bytes.Buffer - _, _ = buf.WriteString("SHOW RETENTION POLICIES ON ") - _, _ = buf.WriteString(QuoteIdent(s.Database)) + _, _ = buf.WriteString("SHOW RETENTION POLICIES") + if s.Database != "" { + _, _ = buf.WriteString(" ON ") + _, _ = buf.WriteString(QuoteIdent(s.Database)) + } return buf.String() } @@ -2632,10 +2722,10 @@ // String returns a string representation of a ShowStatsStatement. func (s *ShowStatsStatement) String() string { var buf bytes.Buffer - _, _ = buf.WriteString("SHOW STATS ") + _, _ = buf.WriteString("SHOW STATS") if s.Module != "" { - _, _ = buf.WriteString("FOR ") - _, _ = buf.WriteString(s.Module) + _, _ = buf.WriteString(" FOR ") + _, _ = buf.WriteString(QuoteString(s.Module)) } return buf.String() } @@ -2676,10 +2766,10 @@ // String returns a string representation of the ShowDiagnosticsStatement. func (s *ShowDiagnosticsStatement) String() string { var buf bytes.Buffer - _, _ = buf.WriteString("SHOW DIAGNOSTICS ") + _, _ = buf.WriteString("SHOW DIAGNOSTICS") if s.Module != "" { - _, _ = buf.WriteString("FOR ") - _, _ = buf.WriteString(s.Module) + _, _ = buf.WriteString(" FOR ") + _, _ = buf.WriteString(QuoteString(s.Module)) } return buf.String() } @@ -2758,6 +2848,10 @@ // ShowTagKeysStatement represents a command for listing tag keys. type ShowTagKeysStatement struct { + // Database to query. If blank, use the default database. + // The database can also be specified per source in the Sources. + Database string + // Data sources that fields are extracted from. Sources Sources @@ -2785,6 +2879,10 @@ var buf bytes.Buffer _, _ = buf.WriteString("SHOW TAG KEYS") + if s.Database != "" { + _, _ = buf.WriteString(" ON ") + _, _ = buf.WriteString(QuoteIdent(s.Database)) + } if s.Sources != nil { _, _ = buf.WriteString(" FROM ") _, _ = buf.WriteString(s.Sources.String()) @@ -2823,6 +2921,10 @@ // ShowTagValuesStatement represents a command for listing tag values. type ShowTagValuesStatement struct { + // Database to query. If blank, use the default database. + // The database can also be specified per source in the Sources. + Database string + // Data source that fields are extracted from. Sources Sources @@ -2851,6 +2953,10 @@ var buf bytes.Buffer _, _ = buf.WriteString("SHOW TAG VALUES") + if s.Database != "" { + _, _ = buf.WriteString(" ON ") + _, _ = buf.WriteString(QuoteIdent(s.Database)) + } if s.Sources != nil { _, _ = buf.WriteString(" FROM ") _, _ = buf.WriteString(s.Sources.String()) @@ -2858,7 +2964,11 @@ _, _ = buf.WriteString(" WITH KEY ") _, _ = buf.WriteString(s.Op.String()) _, _ = buf.WriteString(" ") - _, _ = buf.WriteString(s.TagKeyExpr.String()) + if lit, ok := s.TagKeyExpr.(*StringLiteral); ok { + _, _ = buf.WriteString(QuoteIdent(lit.Val)) + } else { + _, _ = buf.WriteString(s.TagKeyExpr.String()) + } if s.Condition != nil { _, _ = buf.WriteString(" WHERE ") _, _ = buf.WriteString(s.Condition.String()) @@ -2898,6 +3008,10 @@ // ShowFieldKeysStatement represents a command for listing field keys. type ShowFieldKeysStatement struct { + // Database to query. If blank, use the default database. + // The database can also be specified per source in the Sources. + Database string + // Data sources that fields are extracted from. Sources Sources @@ -2917,6 +3031,10 @@ var buf bytes.Buffer _, _ = buf.WriteString("SHOW FIELD KEYS") + if s.Database != "" { + _, _ = buf.WriteString(" ON ") + _, _ = buf.WriteString(QuoteIdent(s.Database)) + } if s.Sources != nil { _, _ = buf.WriteString(" FROM ") _, _ = buf.WriteString(s.Sources.String()) diff -Nru influxdb-1.0.2+dfsg1/influxql/ast_test.go influxdb-1.1.1+dfsg1/influxql/ast_test.go --- influxdb-1.0.2+dfsg1/influxql/ast_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/ast_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -61,77 +61,6 @@ } } -// Ensure the SELECT statement can extract substatements. -func TestSelectStatement_Substatement(t *testing.T) { - var tests = []struct { - stmt string - expr *influxql.VarRef - sub string - err string - }{ - // 0. Single series - { - stmt: `SELECT value FROM myseries WHERE value > 1`, - expr: &influxql.VarRef{Val: "value"}, - sub: `SELECT value FROM myseries WHERE value > 1`, - }, - - // 1. Simple join - { - stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb`, - expr: &influxql.VarRef{Val: "aa.value"}, - sub: `SELECT "aa.value" FROM aa`, - }, - - // 2. Simple merge - { - stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb`, - expr: &influxql.VarRef{Val: "bb.value"}, - sub: `SELECT "bb.value" FROM bb`, - }, - - // 3. Join with condition - { - stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb WHERE aa.host = 'servera' AND bb.host = 'serverb'`, - expr: &influxql.VarRef{Val: "bb.value"}, - sub: `SELECT "bb.value" FROM bb WHERE "bb.host" = 'serverb'`, - }, - - // 4. Join with complex condition - { - stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb WHERE aa.host = 'servera' AND (bb.host = 'serverb' OR bb.host = 'serverc') AND 1 = 2`, - expr: &influxql.VarRef{Val: "bb.value"}, - sub: `SELECT "bb.value" FROM bb WHERE ("bb.host" = 'serverb' OR "bb.host" = 'serverc') AND 1 = 2`, - }, - - // 5. 4 with different condition order - { - stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb WHERE ((bb.host = 'serverb' OR bb.host = 'serverc') AND aa.host = 'servera') AND 1 = 2`, - expr: &influxql.VarRef{Val: "bb.value"}, - sub: `SELECT "bb.value" FROM bb WHERE (("bb.host" = 'serverb' OR "bb.host" = 'serverc')) AND 1 = 2`, - }, - } - - for i, tt := range tests { - // Parse statement. - stmt, err := influxql.NewParser(strings.NewReader(tt.stmt)).ParseStatement() - if err != nil { - t.Fatalf("invalid statement: %q: %s", tt.stmt, err) - } - - // Extract substatement. - sub, err := stmt.(*influxql.SelectStatement).Substatement(tt.expr) - if err != nil { - t.Errorf("%d. %q: unexpected error: %s", i, tt.stmt, err) - continue - } - if substr := sub.String(); tt.sub != substr { - t.Errorf("%d. %q: unexpected substatement:\n\nexp=%s\n\ngot=%s\n\n", i, tt.stmt, tt.sub, substr) - continue - } - } -} - // Ensure the SELECT statement can extract GROUP BY interval. func TestSelectStatement_GroupByInterval(t *testing.T) { q := "SELECT sum(value) from foo where time < now() GROUP BY time(10m)" @@ -461,6 +390,23 @@ stmt: `SELECT mean(*) AS alias FROM cpu`, rewrite: `SELECT mean(value1::float) AS alias_value1, mean(value2::integer) AS alias_value2 FROM cpu`, }, + + // Query regex + { + stmt: `SELECT /1/ FROM cpu`, + rewrite: `SELECT value1::float FROM cpu`, + }, + + { + stmt: `SELECT value1 FROM cpu GROUP BY /h/`, + rewrite: `SELECT value1::float FROM cpu GROUP BY host`, + }, + + // Query regex + { + stmt: `SELECT mean(/1/) FROM cpu`, + rewrite: `SELECT mean(value1::float) AS mean_value1 FROM cpu`, + }, } for i, tt := range tests { @@ -506,6 +452,75 @@ } } +// Test SELECT statement regex conditions rewrite. +func TestSelectStatement_RewriteRegexConditions(t *testing.T) { + var tests = []struct { + in string + out string + }{ + {in: `SELECT value FROM cpu`, out: `SELECT value FROM cpu`}, + {in: `SELECT value FROM cpu WHERE host='server-1'`, out: `SELECT value FROM cpu WHERE host='server-1'`}, + {in: `SELECT value FROM cpu WHERE host = 'server-1'`, out: `SELECT value FROM cpu WHERE host = 'server-1'`}, + {in: `SELECT value FROM cpu WHERE host != 'server-1'`, out: `SELECT value FROM cpu WHERE host != 'server-1'`}, + + // Non matching regex + {in: `SELECT value FROM cpu WHERE host =~ /server-1|server-2|server-3/`, out: `SELECT value FROM cpu WHERE host =~ /server-1|server-2|server-3/`}, + {in: `SELECT value FROM cpu WHERE host =~ /server-1/`, out: `SELECT value FROM cpu WHERE host =~ /server-1/`}, + {in: `SELECT value FROM cpu WHERE host !~ /server-1/`, out: `SELECT value FROM cpu WHERE host !~ /server-1/`}, + {in: `SELECT value FROM cpu WHERE host =~ /^server-1/`, out: `SELECT value FROM cpu WHERE host =~ /^server-1/`}, + {in: `SELECT value FROM cpu WHERE host =~ /server-1$/`, out: `SELECT value FROM cpu WHERE host =~ /server-1$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /\^server-1$/`, out: `SELECT value FROM cpu WHERE host !~ /\^server-1$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /\^$/`, out: `SELECT value FROM cpu WHERE host !~ /\^$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /^server-1\$/`, out: `SELECT value FROM cpu WHERE host !~ /^server-1\$/`}, + {in: `SELECT value FROM cpu WHERE host =~ /^\$/`, out: `SELECT value FROM cpu WHERE host =~ /^\$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /^a/`, out: `SELECT value FROM cpu WHERE host !~ /^a/`}, + + // These regexes are not supported due to the presence of escaped or meta characters. + {in: `SELECT value FROM cpu WHERE host !~ /^(foo|bar)$/`, out: `SELECT value FROM cpu WHERE host !~ /^(foo|bar)$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /^?a$/`, out: `SELECT value FROM cpu WHERE host !~ /^?a$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /^[a-z]$/`, out: `SELECT value FROM cpu WHERE host !~ /^[a-z]$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /^\d$/`, out: `SELECT value FROM cpu WHERE host !~ /^\d$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /^a*$/`, out: `SELECT value FROM cpu WHERE host !~ /^a*$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /^a.b$/`, out: `SELECT value FROM cpu WHERE host !~ /^a.b$/`}, + {in: `SELECT value FROM cpu WHERE host !~ /^ab+$/`, out: `SELECT value FROM cpu WHERE host !~ /^ab+$/`}, + {in: `SELECT value FROM cpu WHERE host =~ /^hello\world$/`, out: `SELECT value FROM cpu WHERE host =~ /^hello\world$/`}, + + // These regexes all match and will be rewritten. + {in: `SELECT value FROM cpu WHERE host !~ /^a[2]$/`, out: `SELECT value FROM cpu WHERE host != 'a2'`}, + {in: `SELECT value FROM cpu WHERE host =~ /^server-1$/`, out: `SELECT value FROM cpu WHERE host = 'server-1'`}, + {in: `SELECT value FROM cpu WHERE host !~ /^server-1$/`, out: `SELECT value FROM cpu WHERE host != 'server-1'`}, + {in: `SELECT value FROM cpu WHERE host =~ /^server 1$/`, out: `SELECT value FROM cpu WHERE host = 'server 1'`}, + {in: `SELECT value FROM cpu WHERE host =~ /^$/`, out: `SELECT value FROM cpu WHERE host = ''`}, + {in: `SELECT value FROM cpu WHERE host !~ /^$/`, out: `SELECT value FROM cpu WHERE host != ''`}, + {in: `SELECT value FROM cpu WHERE host =~ /^server-1$/ OR host =~ /^server-2$/`, out: `SELECT value FROM cpu WHERE host = 'server-1' OR host = 'server-2'`}, + {in: `SELECT value FROM cpu WHERE host =~ /^server-1$/ OR host =~ /^server]a$/`, out: `SELECT value FROM cpu WHERE host = 'server-1' OR host = 'server]a'`}, + {in: `SELECT value FROM cpu WHERE host =~ /^hello\?$/`, out: `SELECT value FROM cpu WHERE host = 'hello?'`}, + {in: `SELECT value FROM cpu WHERE host !~ /^\\$/`, out: `SELECT value FROM cpu WHERE host != '\\'`}, + {in: `SELECT value FROM cpu WHERE host !~ /^\\\$$/`, out: `SELECT value FROM cpu WHERE host != '\\$'`}, + } + + for i, test := range tests { + stmt, err := influxql.NewParser(strings.NewReader(test.in)).ParseStatement() + if err != nil { + t.Fatalf("[Example %d], %v", i, err) + } + + // Rewrite any supported regex conditions. + stmt.(*influxql.SelectStatement).RewriteRegexConditions() + + // Get the expected rewritten statement. + expStmt, err := influxql.NewParser(strings.NewReader(test.out)).ParseStatement() + if err != nil { + t.Fatalf("[Example %d], %v", i, err) + } + + // Compare the (potentially) rewritten AST to the expected AST. + if got, exp := stmt, expStmt; !reflect.DeepEqual(got, exp) { + t.Errorf("[Example %d]\nattempting %v\ngot %v\n%s\n\nexpected %v\n%s\n", i+1, test.in, got, mustMarshalJSON(got), exp, mustMarshalJSON(exp)) + } + } +} + // Test SELECT statement time field rewrite. func TestSelectStatement_RewriteTimeFields(t *testing.T) { var tests = []struct { @@ -770,7 +785,6 @@ // number literal {expr: `time < 10`, min: `0001-01-01T00:00:00Z`, max: `1970-01-01T00:00:00.000000009Z`}, - {expr: `time < 10i`, min: `0001-01-01T00:00:00Z`, max: `1970-01-01T00:00:00.000000009Z`}, // Equality {expr: `time = '2000-01-01 00:00:00'`, min: `2000-01-01T00:00:00Z`, max: `2000-01-01T00:00:00.000000001Z`}, @@ -1368,6 +1382,29 @@ } } +// Parse statements that might appear valid but should return an error. +// If allowed to execute, at least some of these statements would result in a panic. +func TestParse_Errors(t *testing.T) { + for _, tt := range []struct { + tmpl string + good string + bad string + }{ + // Second argument to derivative must be duration + {tmpl: `SELECT derivative(f, %s) FROM m`, good: "1h", bad: "true"}, + } { + good := fmt.Sprintf(tt.tmpl, tt.good) + if _, err := influxql.ParseStatement(good); err != nil { + t.Fatalf("statement %q should have parsed correctly but returned error: %s", good, err) + } + + bad := fmt.Sprintf(tt.tmpl, tt.bad) + if _, err := influxql.ParseStatement(bad); err == nil { + t.Fatalf("statement %q should have resulted in a parse error but did not", bad) + } + } +} + // Valuer represents a simple wrapper around a map to implement the influxql.Valuer interface. type Valuer map[string]interface{} diff -Nru influxdb-1.0.2+dfsg1/influxql/call_iterator.go influxdb-1.1.1+dfsg1/influxql/call_iterator.go --- influxdb-1.0.2+dfsg1/influxql/call_iterator.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/call_iterator.go 2016-12-06 21:36:15.000000000 +0000 @@ -677,12 +677,6 @@ return fn, fn } return &integerReduceFloatIterator{input: newBufIntegerIterator(input), opt: opt, create: createFn}, nil - case StringIterator: - createFn := func() (StringPointAggregator, StringPointEmitter) { - fn := NewStringSliceFuncReducer(StringStddevReduceSlice) - return fn, fn - } - return &stringReduceStringIterator{input: newBufStringIterator(input), opt: opt, create: createFn}, nil default: return nil, fmt.Errorf("unsupported stddev iterator type: %T", input) } @@ -746,11 +740,6 @@ }} } -// StringStddevReduceSlice always returns "". -func StringStddevReduceSlice(a []StringPoint) []StringPoint { - return []StringPoint{{Time: ZeroTime, Value: ""}} -} - // newSpreadIterator returns an iterator for operating on a spread() call. func newSpreadIterator(input Iterator, opt IteratorOptions) (Iterator, error) { switch input := input.(type) { @@ -1227,6 +1216,26 @@ } } +// newCumulativeSumIterator returns an iterator for operating on a cumulative_sum() call. +func newCumulativeSumIterator(input Iterator, opt IteratorOptions) (Iterator, error) { + switch input := input.(type) { + case FloatIterator: + createFn := func() (FloatPointAggregator, FloatPointEmitter) { + fn := NewFloatCumulativeSumReducer() + return fn, fn + } + return newFloatStreamFloatIterator(input, createFn, opt), nil + case IntegerIterator: + createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { + fn := NewIntegerCumulativeSumReducer() + return fn, fn + } + return newIntegerStreamIntegerIterator(input, createFn, opt), nil + default: + return nil, fmt.Errorf("unsupported cumulative sum iterator type: %T", input) + } +} + // newHoltWintersIterator returns an iterator for operating on a elapsed() call. func newHoltWintersIterator(input Iterator, opt IteratorOptions, h, m int, includeFitData bool, interval time.Duration) (Iterator, error) { switch input := input.(type) { @@ -1245,4 +1254,41 @@ default: return nil, fmt.Errorf("unsupported elapsed iterator type: %T", input) } +} + +// NewSampleIterator returns an iterator +func NewSampleIterator(input Iterator, opt IteratorOptions, size int) (Iterator, error) { + return newSampleIterator(input, opt, size) +} + +// newSampleIterator returns an iterator +func newSampleIterator(input Iterator, opt IteratorOptions, size int) (Iterator, error) { + switch input := input.(type) { + case FloatIterator: + createFn := func() (FloatPointAggregator, FloatPointEmitter) { + fn := NewFloatSampleReducer(size) + return fn, fn + } + return &floatReduceFloatIterator{input: newBufFloatIterator(input), opt: opt, create: createFn}, nil + case IntegerIterator: + createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { + fn := NewIntegerSampleReducer(size) + return fn, fn + } + return &integerReduceIntegerIterator{input: newBufIntegerIterator(input), opt: opt, create: createFn}, nil + case BooleanIterator: + createFn := func() (BooleanPointAggregator, BooleanPointEmitter) { + fn := NewBooleanSampleReducer(size) + return fn, fn + } + return &booleanReduceBooleanIterator{input: newBufBooleanIterator(input), opt: opt, create: createFn}, nil + case StringIterator: + createFn := func() (StringPointAggregator, StringPointEmitter) { + fn := NewStringSampleReducer(size) + return fn, fn + } + return &stringReduceStringIterator{input: newBufStringIterator(input), opt: opt, create: createFn}, nil + default: + return nil, fmt.Errorf("unsupported elapsed iterator type: %T", input) + } } diff -Nru influxdb-1.0.2+dfsg1/influxql/call_iterator_test.go influxdb-1.1.1+dfsg1/influxql/call_iterator_test.go --- influxdb-1.0.2+dfsg1/influxql/call_iterator_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/call_iterator_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -844,6 +844,33 @@ } } +func BenchmarkSampleIterator_1k(b *testing.B) { benchmarkSampleIterator(b, 1000) } +func BenchmarkSampleIterator_100k(b *testing.B) { benchmarkSampleIterator(b, 100000) } +func BenchmarkSampleIterator_1M(b *testing.B) { benchmarkSampleIterator(b, 1000000) } + +func benchmarkSampleIterator(b *testing.B, pointN int) { + b.ReportAllocs() + + // Create a lightweight point generator. + p := influxql.FloatPoint{Name: "cpu"} + input := FloatPointGenerator{ + N: pointN, + Fn: func(i int) *influxql.FloatPoint { + p.Value = float64(i) + return &p + }, + } + + for i := 0; i < b.N; i++ { + // Execute call against input. + itr, err := influxql.NewSampleIterator(&input, influxql.IteratorOptions{}, 100) + if err != nil { + b.Fatal(err) + } + influxql.DrainIterator(itr) + } +} + func BenchmarkDistinctIterator_1K(b *testing.B) { benchmarkDistinctIterator(b, 1000) } func BenchmarkDistinctIterator_100K(b *testing.B) { benchmarkDistinctIterator(b, 100000) } func BenchmarkDistinctIterator_1M(b *testing.B) { benchmarkDistinctIterator(b, 1000000) } diff -Nru influxdb-1.0.2+dfsg1/influxql/emitter.go influxdb-1.1.1+dfsg1/influxql/emitter.go --- influxdb-1.0.2+dfsg1/influxql/emitter.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/emitter.go 2016-12-06 21:36:15.000000000 +0000 @@ -113,14 +113,14 @@ // Update range values if lower and emitter is in time ascending order. if e.ascending { - if (itrTime < t) || (itrTime == t && itrName < name) || (itrTime == t && itrName == name && itrTags.ID() < tags.ID()) { + if (itrName < name) || (itrName == name && itrTags.ID() < tags.ID()) || (itrName == name && itrTags.ID() == tags.ID() && itrTime < t) { t, name, tags = itrTime, itrName, itrTags } continue } // Update range values if higher and emitter is in time descending order. - if (itrTime > t) || (itrTime == t && itrName > name) || (itrTime == t && itrName == name && itrTags.ID() > tags.ID()) { + if (itrName < name) || (itrName == name && itrTags.ID() < tags.ID()) || (itrName == name && itrTags.ID() == tags.ID() && itrTime < t) { t, name, tags = itrTime, itrName, itrTags } } diff -Nru influxdb-1.0.2+dfsg1/influxql/functions.gen.go influxdb-1.1.1+dfsg1/influxql/functions.gen.go --- influxdb-1.0.2+dfsg1/influxql/functions.gen.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/functions.gen.go 2016-12-06 21:36:15.000000000 +0000 @@ -6,7 +6,11 @@ package influxql -import "sort" +import ( + "math/rand" + "sort" + "time" +) // FloatPointAggregator aggregates points to produce a single point. type FloatPointAggregator interface { @@ -377,6 +381,51 @@ return nil } +// FloatSampleReduces implements a reservoir sampling to calculate a random subset of points +type FloatSampleReducer struct { + count int // how many points we've iterated over + rng *rand.Rand // random number generator for each reducer + + points floatPoints // the reservoir +} + +// NewFloatSampleReducer creates a new FloatSampleReducer +func NewFloatSampleReducer(size int) *FloatSampleReducer { + return &FloatSampleReducer{ + rng: rand.New(rand.NewSource(time.Now().UnixNano())), // seed with current time as suggested by https://golang.org/pkg/math/rand/ + points: make(floatPoints, size), + } +} + +// AggregateFloat aggregates a point into the reducer. +func (r *FloatSampleReducer) AggregateFloat(p *FloatPoint) { + r.count++ + // Fill the reservoir with the first n points + if r.count-1 < len(r.points) { + r.points[r.count-1] = *p + return + } + + // Generate a random integer between 1 and the count and + // if that number is less than the length of the slice + // replace the point at that index rnd with p. + rnd := rand.Intn(r.count) + if rnd < len(r.points) { + r.points[rnd] = *p + } +} + +// Emit emits the reservoir sample as many points. +func (r *FloatSampleReducer) Emit() []FloatPoint { + min := len(r.points) + if r.count < min { + min = r.count + } + pts := r.points[:min] + sort.Sort(pts) + return pts +} + // IntegerPointAggregator aggregates points to produce a single point. type IntegerPointAggregator interface { AggregateInteger(p *IntegerPoint) @@ -746,6 +795,51 @@ return nil } +// IntegerSampleReduces implements a reservoir sampling to calculate a random subset of points +type IntegerSampleReducer struct { + count int // how many points we've iterated over + rng *rand.Rand // random number generator for each reducer + + points integerPoints // the reservoir +} + +// NewIntegerSampleReducer creates a new IntegerSampleReducer +func NewIntegerSampleReducer(size int) *IntegerSampleReducer { + return &IntegerSampleReducer{ + rng: rand.New(rand.NewSource(time.Now().UnixNano())), // seed with current time as suggested by https://golang.org/pkg/math/rand/ + points: make(integerPoints, size), + } +} + +// AggregateInteger aggregates a point into the reducer. +func (r *IntegerSampleReducer) AggregateInteger(p *IntegerPoint) { + r.count++ + // Fill the reservoir with the first n points + if r.count-1 < len(r.points) { + r.points[r.count-1] = *p + return + } + + // Generate a random integer between 1 and the count and + // if that number is less than the length of the slice + // replace the point at that index rnd with p. + rnd := rand.Intn(r.count) + if rnd < len(r.points) { + r.points[rnd] = *p + } +} + +// Emit emits the reservoir sample as many points. +func (r *IntegerSampleReducer) Emit() []IntegerPoint { + min := len(r.points) + if r.count < min { + min = r.count + } + pts := r.points[:min] + sort.Sort(pts) + return pts +} + // StringPointAggregator aggregates points to produce a single point. type StringPointAggregator interface { AggregateString(p *StringPoint) @@ -1115,6 +1209,51 @@ return nil } +// StringSampleReduces implements a reservoir sampling to calculate a random subset of points +type StringSampleReducer struct { + count int // how many points we've iterated over + rng *rand.Rand // random number generator for each reducer + + points stringPoints // the reservoir +} + +// NewStringSampleReducer creates a new StringSampleReducer +func NewStringSampleReducer(size int) *StringSampleReducer { + return &StringSampleReducer{ + rng: rand.New(rand.NewSource(time.Now().UnixNano())), // seed with current time as suggested by https://golang.org/pkg/math/rand/ + points: make(stringPoints, size), + } +} + +// AggregateString aggregates a point into the reducer. +func (r *StringSampleReducer) AggregateString(p *StringPoint) { + r.count++ + // Fill the reservoir with the first n points + if r.count-1 < len(r.points) { + r.points[r.count-1] = *p + return + } + + // Generate a random integer between 1 and the count and + // if that number is less than the length of the slice + // replace the point at that index rnd with p. + rnd := rand.Intn(r.count) + if rnd < len(r.points) { + r.points[rnd] = *p + } +} + +// Emit emits the reservoir sample as many points. +func (r *StringSampleReducer) Emit() []StringPoint { + min := len(r.points) + if r.count < min { + min = r.count + } + pts := r.points[:min] + sort.Sort(pts) + return pts +} + // BooleanPointAggregator aggregates points to produce a single point. type BooleanPointAggregator interface { AggregateBoolean(p *BooleanPoint) @@ -1483,3 +1622,48 @@ } return nil } + +// BooleanSampleReduces implements a reservoir sampling to calculate a random subset of points +type BooleanSampleReducer struct { + count int // how many points we've iterated over + rng *rand.Rand // random number generator for each reducer + + points booleanPoints // the reservoir +} + +// NewBooleanSampleReducer creates a new BooleanSampleReducer +func NewBooleanSampleReducer(size int) *BooleanSampleReducer { + return &BooleanSampleReducer{ + rng: rand.New(rand.NewSource(time.Now().UnixNano())), // seed with current time as suggested by https://golang.org/pkg/math/rand/ + points: make(booleanPoints, size), + } +} + +// AggregateBoolean aggregates a point into the reducer. +func (r *BooleanSampleReducer) AggregateBoolean(p *BooleanPoint) { + r.count++ + // Fill the reservoir with the first n points + if r.count-1 < len(r.points) { + r.points[r.count-1] = *p + return + } + + // Generate a random integer between 1 and the count and + // if that number is less than the length of the slice + // replace the point at that index rnd with p. + rnd := rand.Intn(r.count) + if rnd < len(r.points) { + r.points[rnd] = *p + } +} + +// Emit emits the reservoir sample as many points. +func (r *BooleanSampleReducer) Emit() []BooleanPoint { + min := len(r.points) + if r.count < min { + min = r.count + } + pts := r.points[:min] + sort.Sort(pts) + return pts +} diff -Nru influxdb-1.0.2+dfsg1/influxql/functions.gen.go.tmpl influxdb-1.1.1+dfsg1/influxql/functions.gen.go.tmpl --- influxdb-1.0.2+dfsg1/influxql/functions.gen.go.tmpl 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/functions.gen.go.tmpl 2016-12-06 21:36:15.000000000 +0000 @@ -1,6 +1,10 @@ package influxql -import "sort" +import ( +"sort" +"time" +"math/rand" +) {{with $types := .}}{{range $k := $types}} @@ -166,5 +170,50 @@ return nil } +// {{$k.Name}}SampleReduces implements a reservoir sampling to calculate a random subset of points +type {{$k.Name}}SampleReducer struct { + count int // how many points we've iterated over + rng *rand.Rand // random number generator for each reducer + + points {{$k.name}}Points // the reservoir +} + +// New{{$k.Name}}SampleReducer creates a new {{$k.Name}}SampleReducer +func New{{$k.Name}}SampleReducer(size int) *{{$k.Name}}SampleReducer { + return &{{$k.Name}}SampleReducer{ + rng: rand.New(rand.NewSource(time.Now().UnixNano())), // seed with current time as suggested by https://golang.org/pkg/math/rand/ + points: make({{$k.name}}Points, size), + } +} + +// Aggregate{{$k.Name}} aggregates a point into the reducer. +func (r *{{$k.Name}}SampleReducer) Aggregate{{$k.Name}}(p *{{$k.Name}}Point) { + r.count++ + // Fill the reservoir with the first n points + if r.count-1 < len(r.points) { + r.points[r.count-1] = *p + return + } + + // Generate a random integer between 1 and the count and + // if that number is less than the length of the slice + // replace the point at that index rnd with p. + rnd := rand.Intn(r.count) + if rnd < len(r.points) { + r.points[rnd] = *p + } +} + +// Emit emits the reservoir sample as many points. +func (r *{{$k.Name}}SampleReducer) Emit() []{{$k.Name}}Point { + min := len(r.points) + if r.count < min { + min = r.count + } + pts := r.points[:min] + sort.Sort(pts) + return pts +} + {{end}}{{end}} diff -Nru influxdb-1.0.2+dfsg1/influxql/functions.go influxdb-1.1.1+dfsg1/influxql/functions.go --- influxdb-1.0.2+dfsg1/influxql/functions.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/functions.go 2016-12-06 21:36:15.000000000 +0000 @@ -357,6 +357,58 @@ } } +// FloatCumulativeSumReducer cumulates the values from each point. +type FloatCumulativeSumReducer struct { + curr FloatPoint +} + +// NewFloatCumulativeSumReducer creates a new FloatCumulativeSumReducer. +func NewFloatCumulativeSumReducer() *FloatCumulativeSumReducer { + return &FloatCumulativeSumReducer{ + curr: FloatPoint{Nil: true}, + } +} + +func (r *FloatCumulativeSumReducer) AggregateFloat(p *FloatPoint) { + r.curr.Value += p.Value + r.curr.Time = p.Time + r.curr.Nil = false +} + +func (r *FloatCumulativeSumReducer) Emit() []FloatPoint { + var pts []FloatPoint + if !r.curr.Nil { + pts = []FloatPoint{r.curr} + } + return pts +} + +// IntegerCumulativeSumReducer cumulates the values from each point. +type IntegerCumulativeSumReducer struct { + curr IntegerPoint +} + +// NewIntegerCumulativeSumReducer creates a new IntegerCumulativeSumReducer. +func NewIntegerCumulativeSumReducer() *IntegerCumulativeSumReducer { + return &IntegerCumulativeSumReducer{ + curr: IntegerPoint{Nil: true}, + } +} + +func (r *IntegerCumulativeSumReducer) AggregateInteger(p *IntegerPoint) { + r.curr.Value += p.Value + r.curr.Time = p.Time + r.curr.Nil = false +} + +func (r *IntegerCumulativeSumReducer) Emit() []IntegerPoint { + var pts []IntegerPoint + if !r.curr.Nil { + pts = []IntegerPoint{r.curr} + } + return pts +} + // FloatHoltWintersReducer forecasts a series into the future. // This is done using the Holt-Winters damped method. // 1. Using the series the initial values are calculated using a SSE. diff -Nru influxdb-1.0.2+dfsg1/influxql/functions_test.go influxdb-1.1.1+dfsg1/influxql/functions_test.go --- influxdb-1.0.2+dfsg1/influxql/functions_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/functions_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -5,7 +5,9 @@ "testing" "time" + "github.com/davecgh/go-spew/spew" "github.com/influxdata/influxdb/influxql" + "github.com/influxdata/influxdb/pkg/deep" ) func almostEqual(got, exp float64) bool { @@ -384,3 +386,108 @@ } } } + +// TestSample_AllSamplesSeen attempts to verify that it is possible +// to get every subsample in a reasonable number of iterations. +// +// The idea here is that 6 iterations should be enough to hit every possible +// sequence atleast once. +func TestSample_AllSamplesSeen(t *testing.T) { + + ps := []influxql.FloatPoint{ + {Time: 1, Value: 1}, + {Time: 2, Value: 2}, + {Time: 3, Value: 3}, + } + + // List of all the possible subsamples + samples := [][]influxql.FloatPoint{ + { + {Time: 1, Value: 1}, + {Time: 2, Value: 2}, + }, + { + {Time: 1, Value: 1}, + {Time: 3, Value: 3}, + }, + { + {Time: 2, Value: 2}, + {Time: 3, Value: 3}, + }, + } + + // 6 iterations should be more than sufficient to garentee that + // we hit every possible subsample. + for i := 0; i < 6; i++ { + s := influxql.NewFloatSampleReducer(2) + for _, p := range ps { + s.AggregateFloat(&p) + } + + points := s.Emit() + + // if samples is empty we've seen every sample, so we're done + if len(samples) == 0 { + return + } + + for i, sample := range samples { + // if we find a sample that it matches, remove it from + // this list of possible samples + if deep.Equal(sample, points) { + samples = append(samples[:i], samples[i+1:]...) + } + } + + } + + // If we missed a sample, report the error + if exp, got := 0, len(samples); exp != got { + t.Fatalf("expected to get every sample: got %d, exp %d", got, exp) + } + +} + +func TestSample_SampleSizeLessThanNumPoints(t *testing.T) { + s := influxql.NewFloatSampleReducer(2) + + ps := []influxql.FloatPoint{ + {Time: 1, Value: 1}, + {Time: 2, Value: 2}, + {Time: 3, Value: 3}, + } + + for _, p := range ps { + s.AggregateFloat(&p) + } + + points := s.Emit() + + if exp, got := 2, len(points); exp != got { + t.Fatalf("unexpected number of points emitted: got %d exp %d", got, exp) + } +} + +func TestSample_SampleSizeGreaterThanNumPoints(t *testing.T) { + s := influxql.NewFloatSampleReducer(4) + + ps := []influxql.FloatPoint{ + {Time: 1, Value: 1}, + {Time: 2, Value: 2}, + {Time: 3, Value: 3}, + } + + for _, p := range ps { + s.AggregateFloat(&p) + } + + points := s.Emit() + + if exp, got := len(ps), len(points); exp != got { + t.Fatalf("unexpected number of points emitted: got %d exp %d", got, exp) + } + + if !deep.Equal(ps, points) { + t.Fatalf("unexpected points: %s", spew.Sdump(points)) + } +} diff -Nru influxdb-1.0.2+dfsg1/influxql/internal/internal.pb.go influxdb-1.1.1+dfsg1/influxql/internal/internal.pb.go --- influxdb-1.0.2+dfsg1/influxql/internal/internal.pb.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/internal/internal.pb.go 2016-12-06 21:36:15.000000000 +0000 @@ -481,41 +481,48 @@ func init() { proto.RegisterFile("internal/internal.proto", fileDescriptorInternal) } var fileDescriptorInternal = []byte{ - // 566 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x53, 0x51, 0x8f, 0xda, 0x3c, - 0x10, 0x14, 0x84, 0x40, 0xb2, 0x81, 0x83, 0xf3, 0xf7, 0x55, 0x44, 0x7d, 0x42, 0xb4, 0xaa, 0x78, - 0xa8, 0x68, 0x85, 0xfa, 0x07, 0x68, 0x39, 0x24, 0xa4, 0x96, 0x3b, 0x01, 0xba, 0x77, 0x17, 0x4c, - 0x64, 0xc9, 0xd8, 0xd4, 0x76, 0x2a, 0xee, 0x37, 0xdf, 0x9f, 0xe8, 0xda, 0x49, 0x0e, 0x7a, 0xa2, - 0x6f, 0xd9, 0xd9, 0xb5, 0x33, 0x3b, 0x33, 0x86, 0x3e, 0x97, 0x96, 0x69, 0x49, 0xc5, 0xa7, 0xea, - 0x63, 0x7c, 0xd4, 0xca, 0x2a, 0x12, 0x71, 0xb9, 0x17, 0xf9, 0xe9, 0x97, 0x18, 0x3e, 0xd7, 0x20, - 0x7c, 0x50, 0xd8, 0x26, 0x6d, 0x68, 0x2c, 0xe9, 0x81, 0xa5, 0xb5, 0x41, 0x7d, 0x14, 0xbb, 0x6a, - 0x43, 0x33, 0x93, 0xd6, 0x5f, 0x2a, 0x8e, 0xbd, 0x00, 0xab, 0x80, 0x24, 0x10, 0x2c, 0xb9, 0x48, - 0x1b, 0x58, 0x44, 0xe4, 0x2d, 0x04, 0xd3, 0xfc, 0x94, 0x86, 0x83, 0x60, 0x94, 0x4c, 0x3a, 0xe3, - 0xea, 0xe2, 0x31, 0x82, 0x84, 0x00, 0x4c, 0xb3, 0x4c, 0xb3, 0x8c, 0x5a, 0xb6, 0x4b, 0x9b, 0x83, - 0xda, 0xa8, 0xe3, 0xb0, 0xb9, 0x50, 0xd4, 0x3e, 0x52, 0x91, 0xb3, 0xb4, 0x85, 0x58, 0x8d, 0xfc, - 0x0f, 0xed, 0x05, 0x12, 0xcc, 0x98, 0x2e, 0xd0, 0x08, 0xd1, 0x80, 0xfc, 0x07, 0xc9, 0xda, 0x6a, - 0x2e, 0xb3, 0x02, 0x8c, 0x11, 0x8c, 0xdd, 0xe8, 0x57, 0xa5, 0x04, 0xa3, 0xb2, 0x40, 0x01, 0xd1, - 0x88, 0x7c, 0x80, 0x70, 0x6d, 0xa9, 0x35, 0x69, 0x82, 0x65, 0x32, 0xe9, 0x9f, 0x69, 0x2c, 0x70, - 0x6f, 0x6a, 0x95, 0xf6, 0xed, 0xa1, 0xf0, 0x64, 0x49, 0x0f, 0xa2, 0x19, 0xb5, 0x74, 0xf3, 0x74, - 0x2c, 0xd6, 0x0d, 0x5f, 0xb1, 0xaa, 0x5f, 0x65, 0x15, 0x5c, 0x63, 0xd5, 0xb8, 0xca, 0x2a, 0x74, - 0xac, 0x86, 0xcf, 0x75, 0xe8, 0x56, 0xff, 0xbf, 0x3f, 0x5a, 0xae, 0xa4, 0x71, 0x4a, 0xde, 0x9d, - 0x8e, 0x1a, 0x7f, 0xeb, 0xce, 0x25, 0x85, 0x78, 0x75, 0x14, 0x2f, 0x26, 0x03, 0x68, 0xce, 0x39, - 0x13, 0x3b, 0x93, 0xde, 0x7a, 0x31, 0x7b, 0xe7, 0x2d, 0x1e, 0xa9, 0x5e, 0xb1, 0x3d, 0xae, 0xd9, - 0x5a, 0xab, 0x5c, 0x6f, 0x99, 0x41, 0x32, 0x6e, 0xe4, 0xcd, 0x79, 0xe4, 0x07, 0xa3, 0x26, 0xd7, - 0xec, 0xc0, 0xd0, 0xca, 0xf7, 0x10, 0x39, 0xe6, 0xfa, 0x37, 0x15, 0x9e, 0x60, 0x32, 0x21, 0x17, - 0x8a, 0x94, 0x1d, 0xb7, 0xf3, 0x0c, 0x4d, 0x95, 0xc6, 0x11, 0xf3, 0x06, 0x7a, 0xa3, 0xe7, 0x5c, - 0x08, 0xef, 0x55, 0x48, 0x6e, 0x21, 0x76, 0xd5, 0xa5, 0x55, 0x08, 0x7d, 0x53, 0x72, 0xc7, 0xdd, - 0x36, 0xde, 0xa7, 0xd8, 0x41, 0xa8, 0xae, 0xb6, 0x3e, 0x21, 0xb1, 0x17, 0xa9, 0x0b, 0xad, 0x3b, - 0xb9, 0xf3, 0x00, 0x78, 0x00, 0x67, 0xa6, 0x66, 0xcb, 0xf0, 0xa0, 0xcc, 0xbc, 0x49, 0x11, 0xe9, - 0x40, 0xf8, 0x9d, 0x1f, 0xb8, 0x4d, 0xdb, 0x7e, 0xe2, 0x06, 0x9a, 0xf7, 0xfb, 0xbd, 0x61, 0x36, - 0xed, 0x54, 0xf5, 0xba, 0xe8, 0xdf, 0x54, 0x57, 0xae, 0xcb, 0x81, 0x6e, 0x35, 0x30, 0x63, 0xbb, - 0x1c, 0x2d, 0xec, 0x79, 0xb5, 0xbf, 0x40, 0xfb, 0x42, 0x03, 0x83, 0x22, 0x84, 0x28, 0xfe, 0xc1, - 0xa0, 0xd4, 0xff, 0x96, 0x6a, 0x98, 0x41, 0x72, 0xa9, 0x5c, 0x99, 0x8c, 0x9f, 0xd4, 0xb0, 0xd2, - 0xa2, 0x3e, 0x74, 0x57, 0xcc, 0x62, 0x0f, 0x17, 0x7e, 0x50, 0x82, 0x6f, 0x9f, 0x7c, 0x3c, 0xe2, - 0x97, 0xf7, 0x12, 0xf8, 0x0a, 0xb7, 0x59, 0x61, 0x54, 0x4e, 0x65, 0x20, 0xf0, 0x9e, 0x85, 0xd9, - 0x50, 0x9d, 0x21, 0xdd, 0x22, 0x0c, 0x1f, 0xcf, 0x9e, 0xf8, 0xbf, 0xe4, 0x18, 0x0b, 0xa7, 0x61, - 0xed, 0xd5, 0xf6, 0xee, 0xf2, 0x60, 0xf8, 0x19, 0x3a, 0x7f, 0x25, 0xd7, 0xaf, 0xcf, 0x34, 0x67, - 0x66, 0x79, 0x3e, 0xe1, 0xdf, 0xed, 0xb2, 0x3c, 0xf1, 0x0e, 0x9a, 0x65, 0x4a, 0x30, 0x54, 0xe8, - 0xd8, 0xc5, 0x3b, 0x76, 0x31, 0x77, 0x43, 0xe1, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1a, 0x06, - 0x51, 0x0d, 0x11, 0x04, 0x00, 0x00, + // 685 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x54, 0xd1, 0x6a, 0xdc, 0x3a, + 0x10, 0xc5, 0xf6, 0x7a, 0x63, 0x6b, 0xb3, 0x37, 0xb9, 0x22, 0xf7, 0x46, 0x94, 0xd2, 0x1a, 0x3f, + 0x19, 0x4a, 0x37, 0x90, 0xd7, 0x42, 0x61, 0xdb, 0x24, 0xb0, 0xd0, 0x6e, 0x82, 0x1c, 0xf2, 0xae, + 0x66, 0x67, 0x8d, 0xc0, 0x2b, 0x6f, 0x65, 0xb9, 0x6c, 0xde, 0xfa, 0x1b, 0xfd, 0x86, 0x7e, 0x4c, + 0x7f, 0xa9, 0x68, 0x64, 0xaf, 0x9d, 0x14, 0x9a, 0x27, 0xcf, 0x39, 0x33, 0x92, 0x7c, 0x66, 0x8e, + 0x44, 0x4e, 0xa5, 0x32, 0xa0, 0x95, 0x28, 0xcf, 0xba, 0x60, 0xb6, 0xd5, 0x95, 0xa9, 0x68, 0x24, + 0xd5, 0xba, 0x6c, 0x76, 0x5f, 0xcb, 0xf4, 0x97, 0x4f, 0xc2, 0x9b, 0x4a, 0x2a, 0x43, 0x29, 0x19, + 0x2d, 0xc5, 0x06, 0x98, 0x97, 0xf8, 0x59, 0xcc, 0x31, 0xb6, 0xdc, 0xad, 0x28, 0x6a, 0xe6, 0x3b, + 0xce, 0xc6, 0xc8, 0xc9, 0x0d, 0xb0, 0x20, 0xf1, 0xb3, 0x80, 0x63, 0x4c, 0x8f, 0x49, 0xb0, 0x94, + 0x25, 0x1b, 0x25, 0x7e, 0x16, 0x71, 0x1b, 0xd2, 0xd7, 0x24, 0x98, 0x37, 0x3b, 0x16, 0x26, 0x41, + 0x36, 0x39, 0x9f, 0xce, 0xba, 0xf3, 0x66, 0xf3, 0x66, 0xc7, 0x6d, 0x86, 0xbe, 0x22, 0x64, 0x5e, + 0x14, 0x1a, 0x0a, 0x61, 0x60, 0xc5, 0xc6, 0x89, 0x97, 0x4d, 0xf9, 0x80, 0xb1, 0xf9, 0xab, 0xb2, + 0x12, 0xe6, 0x4e, 0x94, 0x0d, 0xb0, 0x83, 0xc4, 0xcb, 0x3c, 0x3e, 0x60, 0x68, 0x4a, 0x0e, 0x17, + 0xca, 0x40, 0x01, 0xda, 0x55, 0x44, 0x89, 0x97, 0x05, 0xfc, 0x11, 0x47, 0x13, 0x32, 0xc9, 0x8d, + 0x96, 0xaa, 0x70, 0x25, 0x71, 0xe2, 0x65, 0x31, 0x1f, 0x52, 0x76, 0x97, 0x0f, 0x55, 0x55, 0x82, + 0x50, 0xae, 0x84, 0x24, 0x5e, 0x16, 0xf1, 0x47, 0x1c, 0x7d, 0x4b, 0xc2, 0xdc, 0x08, 0x53, 0xb3, + 0x49, 0xe2, 0x65, 0x93, 0xf3, 0xd3, 0x5e, 0xcc, 0xc2, 0x80, 0x16, 0xa6, 0xd2, 0x98, 0xe6, 0xae, + 0x2a, 0xfd, 0xe9, 0xa1, 0x74, 0xfa, 0x82, 0x44, 0x17, 0xc2, 0x88, 0xdb, 0x87, 0xad, 0xeb, 0x69, + 0xc8, 0xf7, 0xf8, 0x89, 0x38, 0xff, 0x59, 0x71, 0xc1, 0xf3, 0xe2, 0x46, 0xcf, 0x8b, 0x0b, 0xff, + 0x14, 0x97, 0x7e, 0x1f, 0x91, 0xa3, 0x4e, 0xc6, 0xf5, 0xd6, 0xc8, 0x4a, 0xe1, 0x84, 0x2f, 0x77, + 0x5b, 0xcd, 0x3c, 0xdc, 0x12, 0x63, 0x3b, 0x61, 0x3b, 0x4f, 0x3f, 0x09, 0xb2, 0xd8, 0x0d, 0x30, + 0x23, 0xe3, 0x2b, 0x09, 0xe5, 0xaa, 0x66, 0xff, 0xe2, 0x90, 0x8f, 0xfb, 0xbe, 0xdc, 0x09, 0xcd, + 0x61, 0xcd, 0xdb, 0x3c, 0x3d, 0x23, 0x07, 0x79, 0xd5, 0xe8, 0x7b, 0xa8, 0x59, 0x80, 0xa5, 0xff, + 0xf5, 0xa5, 0x9f, 0x41, 0xd4, 0x8d, 0x86, 0x0d, 0x28, 0xc3, 0xbb, 0x2a, 0x3a, 0x23, 0x91, 0x95, + 0xaa, 0xbf, 0x89, 0x12, 0x75, 0x4d, 0xce, 0xe9, 0xa0, 0xe9, 0x6d, 0x86, 0xef, 0x6b, 0x6c, 0x3b, + 0x2f, 0xe4, 0x06, 0x54, 0x6d, 0x7f, 0x1f, 0x3d, 0x17, 0xf3, 0x01, 0x63, 0x05, 0x5d, 0xc9, 0xb2, + 0x44, 0x97, 0x85, 0x1c, 0x63, 0xfa, 0x92, 0xc4, 0xf6, 0x3b, 0xb4, 0x57, 0x4f, 0xd8, 0xec, 0xc7, + 0x4a, 0xad, 0xa4, 0x6d, 0x08, 0x5a, 0x2b, 0xe6, 0x3d, 0x61, 0xb3, 0xb9, 0x11, 0xda, 0xe0, 0x3d, + 0x88, 0x71, 0x36, 0x3d, 0x41, 0x19, 0x39, 0xb8, 0x54, 0x2b, 0xcc, 0x11, 0xcc, 0x75, 0xd0, 0xae, + 0x9b, 0xd7, 0xf7, 0xa0, 0x56, 0x52, 0x15, 0xe8, 0xa6, 0x88, 0xf7, 0x04, 0x3d, 0x21, 0xe1, 0x27, + 0xb9, 0x91, 0x86, 0x1d, 0xe2, 0x2a, 0x07, 0xe8, 0xff, 0x64, 0x7c, 0xbd, 0x5e, 0xd7, 0x60, 0xd8, + 0x14, 0xe9, 0x16, 0x59, 0x3e, 0x77, 0xe5, 0xff, 0x38, 0xde, 0x21, 0x7b, 0x7a, 0xde, 0x2e, 0x38, + 0x72, 0xa7, 0xe7, 0xfd, 0x8a, 0x0b, 0x58, 0x35, 0x5b, 0x60, 0xc7, 0x78, 0x74, 0x8b, 0xd2, 0x77, + 0xe4, 0x70, 0x30, 0x85, 0x9a, 0xbe, 0x21, 0xe1, 0xc2, 0xc0, 0xa6, 0x66, 0xde, 0xdf, 0x86, 0xe5, + 0x6a, 0xd2, 0x1f, 0x1e, 0x99, 0x0c, 0xe8, 0xce, 0xf5, 0x5f, 0x44, 0x0d, 0xad, 0x7f, 0xf6, 0x98, + 0x66, 0xe4, 0x88, 0x83, 0x01, 0x65, 0x7b, 0x78, 0x53, 0x95, 0xf2, 0xfe, 0x01, 0xad, 0x1f, 0xf3, + 0xa7, 0xf4, 0xfe, 0x2d, 0x0a, 0x9c, 0x03, 0xf1, 0x2d, 0x3a, 0x21, 0x21, 0x87, 0x02, 0x76, 0xad, + 0xd3, 0x1d, 0xb0, 0xe7, 0x2d, 0xea, 0x5b, 0xa1, 0x0b, 0x30, 0xad, 0xbf, 0xf7, 0x38, 0x7d, 0xdf, + 0xdb, 0x08, 0xff, 0xab, 0xd1, 0x02, 0xe7, 0xe9, 0x61, 0x5f, 0xf6, 0x78, 0xd0, 0x62, 0x7f, 0xd8, + 0xe2, 0x74, 0x4e, 0xa6, 0x8f, 0x6e, 0x38, 0xf6, 0x16, 0xb4, 0x84, 0x7a, 0xd9, 0xee, 0xd1, 0x41, + 0xbb, 0x05, 0xbe, 0xa2, 0xcb, 0x6e, 0x0b, 0x87, 0xd2, 0x19, 0x19, 0xbb, 0xcb, 0x60, 0x2f, 0xd0, + 0x9d, 0x28, 0xdb, 0xd7, 0xd5, 0x86, 0xf8, 0x90, 0xda, 0xc7, 0xc1, 0x77, 0xae, 0xb4, 0xf1, 0xef, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x01, 0x5d, 0x11, 0xb2, 0x05, 0x00, 0x00, } diff -Nru influxdb-1.0.2+dfsg1/influxql/iterator.gen.go influxdb-1.1.1+dfsg1/influxql/iterator.gen.go --- influxdb-1.0.2+dfsg1/influxql/iterator.gen.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/iterator.gen.go 2016-12-06 21:36:15.000000000 +0000 @@ -673,6 +673,23 @@ } switch itr.opt.Fill { + case LinearFill: + if !itr.prev.Nil { + next, err := itr.input.peek() + if err != nil { + return nil, err + } + if next != nil { + interval := int64(itr.opt.Interval.Duration) + start := itr.window.time / interval + p.Value = linearFloat(start, itr.prev.Time/interval, next.Time/interval, itr.prev.Value, next.Value) + } else { + p.Nil = true + } + } else { + p.Nil = true + } + case NullFill: p.Nil = true case NumberFill: @@ -1195,9 +1212,29 @@ // floatExprIterator executes a function to modify an existing point // for every output of the input iterator. type floatExprIterator struct { - left *bufFloatIterator - right *bufFloatIterator - fn floatExprFunc + left *bufFloatIterator + right *bufFloatIterator + fn floatExprFunc + points []FloatPoint // must be size 2 + storePrev bool +} + +func newFloatExprIterator(left, right FloatIterator, opt IteratorOptions, fn func(a, b float64) float64) *floatExprIterator { + var points []FloatPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []FloatPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToFloat(opt.FillValue) + points = []FloatPoint{{Value: value}, {Value: value}} + } + return &floatExprIterator{ + left: newBufFloatIterator(left), + right: newBufFloatIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *floatExprIterator) Stats() IteratorStats { @@ -1213,24 +1250,70 @@ } func (itr *floatExprIterator) Next() (*FloatPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + if a.Nil { + return a, nil + } else if b.Nil { + return b, nil + } + a.Value = itr.fn(a.Value, b.Value) + return a, nil + } - return itr.fn(a, b), nil } // floatExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type floatExprFunc func(a *FloatPoint, b *FloatPoint) *FloatPoint +type floatExprFunc func(a, b float64) float64 // floatReduceIntegerIterator executes a reducer for every interval and buffers the result. type floatReduceIntegerIterator struct { @@ -1433,9 +1516,29 @@ // floatIntegerExprIterator executes a function to modify an existing point // for every output of the input iterator. type floatIntegerExprIterator struct { - left *bufFloatIterator - right *bufFloatIterator - fn floatIntegerExprFunc + left *bufFloatIterator + right *bufFloatIterator + fn floatIntegerExprFunc + points []FloatPoint // must be size 2 + storePrev bool +} + +func newFloatIntegerExprIterator(left, right FloatIterator, opt IteratorOptions, fn func(a, b float64) int64) *floatIntegerExprIterator { + var points []FloatPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []FloatPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToFloat(opt.FillValue) + points = []FloatPoint{{Value: value}, {Value: value}} + } + return &floatIntegerExprIterator{ + left: newBufFloatIterator(left), + right: newBufFloatIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *floatIntegerExprIterator) Stats() IteratorStats { @@ -1451,24 +1554,74 @@ } func (itr *floatIntegerExprIterator) Next() (*IntegerPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &IntegerPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // floatIntegerExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type floatIntegerExprFunc func(a *FloatPoint, b *FloatPoint) *IntegerPoint +type floatIntegerExprFunc func(a, b float64) int64 // floatReduceStringIterator executes a reducer for every interval and buffers the result. type floatReduceStringIterator struct { @@ -1671,9 +1824,29 @@ // floatStringExprIterator executes a function to modify an existing point // for every output of the input iterator. type floatStringExprIterator struct { - left *bufFloatIterator - right *bufFloatIterator - fn floatStringExprFunc + left *bufFloatIterator + right *bufFloatIterator + fn floatStringExprFunc + points []FloatPoint // must be size 2 + storePrev bool +} + +func newFloatStringExprIterator(left, right FloatIterator, opt IteratorOptions, fn func(a, b float64) string) *floatStringExprIterator { + var points []FloatPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []FloatPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToFloat(opt.FillValue) + points = []FloatPoint{{Value: value}, {Value: value}} + } + return &floatStringExprIterator{ + left: newBufFloatIterator(left), + right: newBufFloatIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *floatStringExprIterator) Stats() IteratorStats { @@ -1689,24 +1862,74 @@ } func (itr *floatStringExprIterator) Next() (*StringPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &StringPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // floatStringExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type floatStringExprFunc func(a *FloatPoint, b *FloatPoint) *StringPoint +type floatStringExprFunc func(a, b float64) string // floatReduceBooleanIterator executes a reducer for every interval and buffers the result. type floatReduceBooleanIterator struct { @@ -1909,9 +2132,29 @@ // floatBooleanExprIterator executes a function to modify an existing point // for every output of the input iterator. type floatBooleanExprIterator struct { - left *bufFloatIterator - right *bufFloatIterator - fn floatBooleanExprFunc + left *bufFloatIterator + right *bufFloatIterator + fn floatBooleanExprFunc + points []FloatPoint // must be size 2 + storePrev bool +} + +func newFloatBooleanExprIterator(left, right FloatIterator, opt IteratorOptions, fn func(a, b float64) bool) *floatBooleanExprIterator { + var points []FloatPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []FloatPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToFloat(opt.FillValue) + points = []FloatPoint{{Value: value}, {Value: value}} + } + return &floatBooleanExprIterator{ + left: newBufFloatIterator(left), + right: newBufFloatIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *floatBooleanExprIterator) Stats() IteratorStats { @@ -1927,24 +2170,74 @@ } func (itr *floatBooleanExprIterator) Next() (*BooleanPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &BooleanPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // floatBooleanExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type floatBooleanExprFunc func(a *FloatPoint, b *FloatPoint) *BooleanPoint +type floatBooleanExprFunc func(a, b float64) bool // floatTransformIterator executes a function to modify an existing point for every // output of the input iterator. @@ -2742,6 +3035,23 @@ } switch itr.opt.Fill { + case LinearFill: + if !itr.prev.Nil { + next, err := itr.input.peek() + if err != nil { + return nil, err + } + if next != nil { + interval := int64(itr.opt.Interval.Duration) + start := itr.window.time / interval + p.Value = linearInteger(start, itr.prev.Time/interval, next.Time/interval, itr.prev.Value, next.Value) + } else { + p.Nil = true + } + } else { + p.Nil = true + } + case NullFill: p.Nil = true case NumberFill: @@ -3261,9 +3571,29 @@ // integerFloatExprIterator executes a function to modify an existing point // for every output of the input iterator. type integerFloatExprIterator struct { - left *bufIntegerIterator - right *bufIntegerIterator - fn integerFloatExprFunc + left *bufIntegerIterator + right *bufIntegerIterator + fn integerFloatExprFunc + points []IntegerPoint // must be size 2 + storePrev bool +} + +func newIntegerFloatExprIterator(left, right IntegerIterator, opt IteratorOptions, fn func(a, b int64) float64) *integerFloatExprIterator { + var points []IntegerPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []IntegerPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToInteger(opt.FillValue) + points = []IntegerPoint{{Value: value}, {Value: value}} + } + return &integerFloatExprIterator{ + left: newBufIntegerIterator(left), + right: newBufIntegerIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *integerFloatExprIterator) Stats() IteratorStats { @@ -3279,24 +3609,74 @@ } func (itr *integerFloatExprIterator) Next() (*FloatPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &FloatPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // integerFloatExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type integerFloatExprFunc func(a *IntegerPoint, b *IntegerPoint) *FloatPoint +type integerFloatExprFunc func(a, b int64) float64 // integerReduceIntegerIterator executes a reducer for every interval and buffers the result. type integerReduceIntegerIterator struct { @@ -3499,9 +3879,29 @@ // integerExprIterator executes a function to modify an existing point // for every output of the input iterator. type integerExprIterator struct { - left *bufIntegerIterator - right *bufIntegerIterator - fn integerExprFunc + left *bufIntegerIterator + right *bufIntegerIterator + fn integerExprFunc + points []IntegerPoint // must be size 2 + storePrev bool +} + +func newIntegerExprIterator(left, right IntegerIterator, opt IteratorOptions, fn func(a, b int64) int64) *integerExprIterator { + var points []IntegerPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []IntegerPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToInteger(opt.FillValue) + points = []IntegerPoint{{Value: value}, {Value: value}} + } + return &integerExprIterator{ + left: newBufIntegerIterator(left), + right: newBufIntegerIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *integerExprIterator) Stats() IteratorStats { @@ -3517,24 +3917,70 @@ } func (itr *integerExprIterator) Next() (*IntegerPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + if a.Nil { + return a, nil + } else if b.Nil { + return b, nil + } + a.Value = itr.fn(a.Value, b.Value) + return a, nil + } - return itr.fn(a, b), nil } // integerExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type integerExprFunc func(a *IntegerPoint, b *IntegerPoint) *IntegerPoint +type integerExprFunc func(a, b int64) int64 // integerReduceStringIterator executes a reducer for every interval and buffers the result. type integerReduceStringIterator struct { @@ -3737,9 +4183,29 @@ // integerStringExprIterator executes a function to modify an existing point // for every output of the input iterator. type integerStringExprIterator struct { - left *bufIntegerIterator - right *bufIntegerIterator - fn integerStringExprFunc + left *bufIntegerIterator + right *bufIntegerIterator + fn integerStringExprFunc + points []IntegerPoint // must be size 2 + storePrev bool +} + +func newIntegerStringExprIterator(left, right IntegerIterator, opt IteratorOptions, fn func(a, b int64) string) *integerStringExprIterator { + var points []IntegerPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []IntegerPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToInteger(opt.FillValue) + points = []IntegerPoint{{Value: value}, {Value: value}} + } + return &integerStringExprIterator{ + left: newBufIntegerIterator(left), + right: newBufIntegerIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *integerStringExprIterator) Stats() IteratorStats { @@ -3755,24 +4221,74 @@ } func (itr *integerStringExprIterator) Next() (*StringPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &StringPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // integerStringExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type integerStringExprFunc func(a *IntegerPoint, b *IntegerPoint) *StringPoint +type integerStringExprFunc func(a, b int64) string // integerReduceBooleanIterator executes a reducer for every interval and buffers the result. type integerReduceBooleanIterator struct { @@ -3975,9 +4491,29 @@ // integerBooleanExprIterator executes a function to modify an existing point // for every output of the input iterator. type integerBooleanExprIterator struct { - left *bufIntegerIterator - right *bufIntegerIterator - fn integerBooleanExprFunc + left *bufIntegerIterator + right *bufIntegerIterator + fn integerBooleanExprFunc + points []IntegerPoint // must be size 2 + storePrev bool +} + +func newIntegerBooleanExprIterator(left, right IntegerIterator, opt IteratorOptions, fn func(a, b int64) bool) *integerBooleanExprIterator { + var points []IntegerPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []IntegerPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToInteger(opt.FillValue) + points = []IntegerPoint{{Value: value}, {Value: value}} + } + return &integerBooleanExprIterator{ + left: newBufIntegerIterator(left), + right: newBufIntegerIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *integerBooleanExprIterator) Stats() IteratorStats { @@ -3993,24 +4529,74 @@ } func (itr *integerBooleanExprIterator) Next() (*BooleanPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil - } - return itr.fn(a, b), nil -} - -// integerBooleanExprFunc creates or modifies a point by combining two -// points. The point passed in may be modified and returned rather than + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &BooleanPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + + } +} + +// integerBooleanExprFunc creates or modifies a point by combining two +// points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type integerBooleanExprFunc func(a *IntegerPoint, b *IntegerPoint) *BooleanPoint +type integerBooleanExprFunc func(a, b int64) bool // integerTransformIterator executes a function to modify an existing point for every // output of the input iterator. @@ -4808,6 +5394,8 @@ } switch itr.opt.Fill { + case LinearFill: + fallthrough case NullFill: p.Nil = true case NumberFill: @@ -5327,9 +5915,29 @@ // stringFloatExprIterator executes a function to modify an existing point // for every output of the input iterator. type stringFloatExprIterator struct { - left *bufStringIterator - right *bufStringIterator - fn stringFloatExprFunc + left *bufStringIterator + right *bufStringIterator + fn stringFloatExprFunc + points []StringPoint // must be size 2 + storePrev bool +} + +func newStringFloatExprIterator(left, right StringIterator, opt IteratorOptions, fn func(a, b string) float64) *stringFloatExprIterator { + var points []StringPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []StringPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToString(opt.FillValue) + points = []StringPoint{{Value: value}, {Value: value}} + } + return &stringFloatExprIterator{ + left: newBufStringIterator(left), + right: newBufStringIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *stringFloatExprIterator) Stats() IteratorStats { @@ -5345,24 +5953,74 @@ } func (itr *stringFloatExprIterator) Next() (*FloatPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &FloatPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // stringFloatExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type stringFloatExprFunc func(a *StringPoint, b *StringPoint) *FloatPoint +type stringFloatExprFunc func(a, b string) float64 // stringReduceIntegerIterator executes a reducer for every interval and buffers the result. type stringReduceIntegerIterator struct { @@ -5565,9 +6223,29 @@ // stringIntegerExprIterator executes a function to modify an existing point // for every output of the input iterator. type stringIntegerExprIterator struct { - left *bufStringIterator - right *bufStringIterator - fn stringIntegerExprFunc + left *bufStringIterator + right *bufStringIterator + fn stringIntegerExprFunc + points []StringPoint // must be size 2 + storePrev bool +} + +func newStringIntegerExprIterator(left, right StringIterator, opt IteratorOptions, fn func(a, b string) int64) *stringIntegerExprIterator { + var points []StringPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []StringPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToString(opt.FillValue) + points = []StringPoint{{Value: value}, {Value: value}} + } + return &stringIntegerExprIterator{ + left: newBufStringIterator(left), + right: newBufStringIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *stringIntegerExprIterator) Stats() IteratorStats { @@ -5583,24 +6261,74 @@ } func (itr *stringIntegerExprIterator) Next() (*IntegerPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &IntegerPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // stringIntegerExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type stringIntegerExprFunc func(a *StringPoint, b *StringPoint) *IntegerPoint +type stringIntegerExprFunc func(a, b string) int64 // stringReduceStringIterator executes a reducer for every interval and buffers the result. type stringReduceStringIterator struct { @@ -5803,9 +6531,29 @@ // stringExprIterator executes a function to modify an existing point // for every output of the input iterator. type stringExprIterator struct { - left *bufStringIterator - right *bufStringIterator - fn stringExprFunc + left *bufStringIterator + right *bufStringIterator + fn stringExprFunc + points []StringPoint // must be size 2 + storePrev bool +} + +func newStringExprIterator(left, right StringIterator, opt IteratorOptions, fn func(a, b string) string) *stringExprIterator { + var points []StringPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []StringPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToString(opt.FillValue) + points = []StringPoint{{Value: value}, {Value: value}} + } + return &stringExprIterator{ + left: newBufStringIterator(left), + right: newBufStringIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *stringExprIterator) Stats() IteratorStats { @@ -5821,24 +6569,70 @@ } func (itr *stringExprIterator) Next() (*StringPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + if a.Nil { + return a, nil + } else if b.Nil { + return b, nil + } + a.Value = itr.fn(a.Value, b.Value) + return a, nil + } - return itr.fn(a, b), nil } // stringExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type stringExprFunc func(a *StringPoint, b *StringPoint) *StringPoint +type stringExprFunc func(a, b string) string // stringReduceBooleanIterator executes a reducer for every interval and buffers the result. type stringReduceBooleanIterator struct { @@ -6041,9 +6835,29 @@ // stringBooleanExprIterator executes a function to modify an existing point // for every output of the input iterator. type stringBooleanExprIterator struct { - left *bufStringIterator - right *bufStringIterator - fn stringBooleanExprFunc + left *bufStringIterator + right *bufStringIterator + fn stringBooleanExprFunc + points []StringPoint // must be size 2 + storePrev bool +} + +func newStringBooleanExprIterator(left, right StringIterator, opt IteratorOptions, fn func(a, b string) bool) *stringBooleanExprIterator { + var points []StringPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []StringPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToString(opt.FillValue) + points = []StringPoint{{Value: value}, {Value: value}} + } + return &stringBooleanExprIterator{ + left: newBufStringIterator(left), + right: newBufStringIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *stringBooleanExprIterator) Stats() IteratorStats { @@ -6059,24 +6873,74 @@ } func (itr *stringBooleanExprIterator) Next() (*BooleanPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &BooleanPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // stringBooleanExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type stringBooleanExprFunc func(a *StringPoint, b *StringPoint) *BooleanPoint +type stringBooleanExprFunc func(a, b string) bool // stringTransformIterator executes a function to modify an existing point for every // output of the input iterator. @@ -6874,6 +7738,8 @@ } switch itr.opt.Fill { + case LinearFill: + fallthrough case NullFill: p.Nil = true case NumberFill: @@ -7393,9 +8259,29 @@ // booleanFloatExprIterator executes a function to modify an existing point // for every output of the input iterator. type booleanFloatExprIterator struct { - left *bufBooleanIterator - right *bufBooleanIterator - fn booleanFloatExprFunc + left *bufBooleanIterator + right *bufBooleanIterator + fn booleanFloatExprFunc + points []BooleanPoint // must be size 2 + storePrev bool +} + +func newBooleanFloatExprIterator(left, right BooleanIterator, opt IteratorOptions, fn func(a, b bool) float64) *booleanFloatExprIterator { + var points []BooleanPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []BooleanPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToBoolean(opt.FillValue) + points = []BooleanPoint{{Value: value}, {Value: value}} + } + return &booleanFloatExprIterator{ + left: newBufBooleanIterator(left), + right: newBufBooleanIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *booleanFloatExprIterator) Stats() IteratorStats { @@ -7411,24 +8297,74 @@ } func (itr *booleanFloatExprIterator) Next() (*FloatPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &FloatPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // booleanFloatExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type booleanFloatExprFunc func(a *BooleanPoint, b *BooleanPoint) *FloatPoint +type booleanFloatExprFunc func(a, b bool) float64 // booleanReduceIntegerIterator executes a reducer for every interval and buffers the result. type booleanReduceIntegerIterator struct { @@ -7631,9 +8567,29 @@ // booleanIntegerExprIterator executes a function to modify an existing point // for every output of the input iterator. type booleanIntegerExprIterator struct { - left *bufBooleanIterator - right *bufBooleanIterator - fn booleanIntegerExprFunc + left *bufBooleanIterator + right *bufBooleanIterator + fn booleanIntegerExprFunc + points []BooleanPoint // must be size 2 + storePrev bool +} + +func newBooleanIntegerExprIterator(left, right BooleanIterator, opt IteratorOptions, fn func(a, b bool) int64) *booleanIntegerExprIterator { + var points []BooleanPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []BooleanPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToBoolean(opt.FillValue) + points = []BooleanPoint{{Value: value}, {Value: value}} + } + return &booleanIntegerExprIterator{ + left: newBufBooleanIterator(left), + right: newBufBooleanIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *booleanIntegerExprIterator) Stats() IteratorStats { @@ -7649,24 +8605,74 @@ } func (itr *booleanIntegerExprIterator) Next() (*IntegerPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &IntegerPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // booleanIntegerExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type booleanIntegerExprFunc func(a *BooleanPoint, b *BooleanPoint) *IntegerPoint +type booleanIntegerExprFunc func(a, b bool) int64 // booleanReduceStringIterator executes a reducer for every interval and buffers the result. type booleanReduceStringIterator struct { @@ -7869,9 +8875,29 @@ // booleanStringExprIterator executes a function to modify an existing point // for every output of the input iterator. type booleanStringExprIterator struct { - left *bufBooleanIterator - right *bufBooleanIterator - fn booleanStringExprFunc + left *bufBooleanIterator + right *bufBooleanIterator + fn booleanStringExprFunc + points []BooleanPoint // must be size 2 + storePrev bool +} + +func newBooleanStringExprIterator(left, right BooleanIterator, opt IteratorOptions, fn func(a, b bool) string) *booleanStringExprIterator { + var points []BooleanPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []BooleanPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToBoolean(opt.FillValue) + points = []BooleanPoint{{Value: value}, {Value: value}} + } + return &booleanStringExprIterator{ + left: newBufBooleanIterator(left), + right: newBufBooleanIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *booleanStringExprIterator) Stats() IteratorStats { @@ -7887,24 +8913,74 @@ } func (itr *booleanStringExprIterator) Next() (*StringPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + p := &StringPoint{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil + } - return itr.fn(a, b), nil } // booleanStringExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type booleanStringExprFunc func(a *BooleanPoint, b *BooleanPoint) *StringPoint +type booleanStringExprFunc func(a, b bool) string // booleanReduceBooleanIterator executes a reducer for every interval and buffers the result. type booleanReduceBooleanIterator struct { @@ -8107,9 +9183,29 @@ // booleanExprIterator executes a function to modify an existing point // for every output of the input iterator. type booleanExprIterator struct { - left *bufBooleanIterator - right *bufBooleanIterator - fn booleanExprFunc + left *bufBooleanIterator + right *bufBooleanIterator + fn booleanExprFunc + points []BooleanPoint // must be size 2 + storePrev bool +} + +func newBooleanExprIterator(left, right BooleanIterator, opt IteratorOptions, fn func(a, b bool) bool) *booleanExprIterator { + var points []BooleanPoint + switch opt.Fill { + case NullFill, PreviousFill: + points = []BooleanPoint{{Nil: true}, {Nil: true}} + case NumberFill: + value := castToBoolean(opt.FillValue) + points = []BooleanPoint{{Value: value}, {Value: value}} + } + return &booleanExprIterator{ + left: newBufBooleanIterator(left), + right: newBufBooleanIterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *booleanExprIterator) Stats() IteratorStats { @@ -8125,24 +9221,70 @@ } func (itr *booleanExprIterator) Next() (*BooleanPoint, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + + if a.Nil { + return a, nil + } else if b.Nil { + return b, nil + } + a.Value = itr.fn(a.Value, b.Value) + return a, nil + } - return itr.fn(a, b), nil } // booleanExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type booleanExprFunc func(a *BooleanPoint, b *BooleanPoint) *BooleanPoint +type booleanExprFunc func(a, b bool) bool // booleanTransformIterator executes a function to modify an existing point for every // output of the input iterator. diff -Nru influxdb-1.0.2+dfsg1/influxql/iterator.gen.go.tmpl influxdb-1.1.1+dfsg1/influxql/iterator.gen.go.tmpl --- influxdb-1.0.2+dfsg1/influxql/iterator.gen.go.tmpl 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/iterator.gen.go.tmpl 2016-12-06 21:36:15.000000000 +0000 @@ -671,6 +671,26 @@ } switch itr.opt.Fill { + case LinearFill: + {{- if or (eq $k.Name "Float") (eq $k.Name "Integer")}} + if !itr.prev.Nil { + next, err := itr.input.peek() + if err != nil { + return nil, err + } + if next != nil { + interval := int64(itr.opt.Interval.Duration) + start := itr.window.time / interval + p.Value = linear{{$k.Name}}(start, itr.prev.Time/interval, next.Time/interval, itr.prev.Value, next.Value) + } else { + p.Nil = true + } + } else { + p.Nil = true + } + {{else}} + fallthrough + {{- end}} case NullFill: p.Nil = true case NumberFill: @@ -1193,9 +1213,29 @@ // {{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator executes a function to modify an existing point // for every output of the input iterator. type {{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator struct { - left *buf{{$k.Name}}Iterator - right *buf{{$k.Name}}Iterator - fn {{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprFunc + left *buf{{$k.Name}}Iterator + right *buf{{$k.Name}}Iterator + fn {{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprFunc + points []{{$k.Name}}Point // must be size 2 + storePrev bool +} + +func new{{$k.Name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator(left, right {{$k.Name}}Iterator, opt IteratorOptions, fn func(a, b {{$k.Type}}) {{$v.Type}}) *{{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator { + var points []{{$k.Name}}Point + switch opt.Fill { + case NullFill, PreviousFill: + points = []{{$k.Name}}Point{ {Nil: true}, {Nil: true} } + case NumberFill: + value := castTo{{$k.Name}}(opt.FillValue) + points = []{{$k.Name}}Point{ {Value: value}, {Value: value} } + } + return &{{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator{ + left: newBuf{{$k.Name}}Iterator(left), + right: newBuf{{$k.Name}}Iterator(right), + points: points, + fn: fn, + storePrev: opt.Fill == PreviousFill, + } } func (itr *{{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator) Stats() IteratorStats { @@ -1211,24 +1251,83 @@ } func (itr *{{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator) Next() (*{{$v.Name}}Point, error) { - a, err := itr.left.Next() - if err != nil { - return nil, err - } - b, err := itr.right.Next() - if err != nil { - return nil, err - } else if a == nil && b == nil { - return nil, nil + for { + a, err := itr.left.Next() + if err != nil { + return nil, err + } + b, err := itr.right.Next() + if err != nil { + return nil, err + } + + if a == nil && b == nil { + return nil, nil + } else if itr.points == nil && (a == nil || b == nil ) { + return nil, nil + } + + if a != nil && b != nil { + if a.Time > b.Time { + itr.left.unread(a) + a = nil + } else if a.Time < b.Time { + itr.right.unread(b) + b = nil + } + } + + if a == nil || a.Nil { + if itr.points == nil { + continue + } + p := *b + p.Value = itr.points[0].Value + p.Nil = itr.points[0].Nil + a = &p + } else if b == nil || b.Nil { + if itr.points == nil { + continue + } + p := *a + p.Value = itr.points[1].Value + p.Nil = itr.points[1].Nil + b = &p + } + + if itr.storePrev { + itr.points[0], itr.points[1] = *a, *b + } + +{{if eq $k.Name $v.Name}} + if a.Nil { + return a, nil + } else if b.Nil { + return b, nil + } + a.Value = itr.fn(a.Value, b.Value) + return a, nil +{{else}} + p := &{{$v.Name}}Point{ + Name: a.Name, + Tags: a.Tags, + Time: a.Time, + Nil: a.Nil || b.Nil, + Aggregated: a.Aggregated, + } + if !p.Nil { + p.Value = itr.fn(a.Value, b.Value) + } + return p, nil +{{end}} } - return itr.fn(a, b), nil } // {{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at // least one of the points will be non-nil. -type {{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprFunc func(a *{{$k.Name}}Point, b *{{$k.Name}}Point) *{{$v.Name}}Point +type {{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprFunc func(a, b {{$k.Type}}) {{$v.Type}} {{end}} // {{$k.name}}TransformIterator executes a function to modify an existing point for every diff -Nru influxdb-1.0.2+dfsg1/influxql/linear.go influxdb-1.1.1+dfsg1/influxql/linear.go --- influxdb-1.0.2+dfsg1/influxql/linear.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/linear.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,21 @@ +package influxql + +// linearFloat computes the the slope of the line between the points (previousTime, previousValue) and (nextTime, nextValue) +// and returns the value of the point on the line with time windowTime +// y = mx + b +func linearFloat(windowTime, previousTime, nextTime int64, previousValue, nextValue float64) float64 { + m := (nextValue - previousValue) / float64(nextTime-previousTime) // the slope of the line + x := float64(windowTime - previousTime) // how far into the interval we are + b := previousValue + return m*x + b +} + +// linearInteger computes the the slope of the line between the points (previousTime, previousValue) and (nextTime, nextValue) +// and returns the value of the point on the line with time windowTime +// y = mx + b +func linearInteger(windowTime, previousTime, nextTime int64, previousValue, nextValue int64) int64 { + m := float64(nextValue-previousValue) / float64(nextTime-previousTime) // the slope of the line + x := float64(windowTime - previousTime) // how far into the interval we are + b := float64(previousValue) + return int64(m*x + b) +} diff -Nru influxdb-1.0.2+dfsg1/influxql/monitor.go influxdb-1.1.1+dfsg1/influxql/monitor.go --- influxdb-1.0.2+dfsg1/influxql/monitor.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/monitor.go 2016-12-06 21:36:15.000000000 +0000 @@ -13,7 +13,7 @@ case <-ticker.C: stats := itrs.Stats() if stats.PointN >= limit { - return ErrMaxPointsReached + return ErrMaxSelectPointsLimitExceeded(stats.PointN, limit) } case <-closing: return nil diff -Nru influxdb-1.0.2+dfsg1/influxql/parser.go influxdb-1.1.1+dfsg1/influxql/parser.go --- influxdb-1.0.2+dfsg1/influxql/parser.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/parser.go 2016-12-06 21:36:15.000000000 +0000 @@ -475,10 +475,17 @@ stmt.Database = ident // Loop through option tokens (DURATION, REPLICATION, SHARD DURATION, DEFAULT, etc.). - maxNumOptions := 4 + found := make(map[Token]struct{}) Loop: - for i := 0; i < maxNumOptions; i++ { + for { tok, pos, lit := p.scanIgnoreWhitespace() + if _, ok := found[tok]; ok { + return nil, &ParseError{ + Message: fmt.Sprintf("found duplicate %s option", tok), + Pos: pos, + } + } + switch tok { case DURATION: d, err := p.parseDuration() @@ -506,12 +513,13 @@ case DEFAULT: stmt.Default = true default: - if i < 1 { + if len(found) == 0 { return nil, newParseError(tokstr(tok, lit), []string{"DURATION", "REPLICATION", "SHARD", "DEFAULT"}, pos) } p.unscan() break Loop } + found[tok] = struct{}{} } return stmt, nil @@ -1022,6 +1030,25 @@ if stmt.Sources, err = p.parseSources(); err != nil { return nil, err } + + var err error + WalkFunc(stmt.Sources, func(n Node) { + if t, ok := n.(*Measurement); ok { + // Don't allow database or retention policy in from clause for delete + // statement. They apply to the selected database across all retention + // policies. + if t.Database != "" { + err = &ParseError{Message: "database not supported"} + } + if t.RetentionPolicy != "" { + err = &ParseError{Message: "retention policy not supported"} + } + } + }) + if err != nil { + return nil, err + } + } else { p.unscan() } @@ -1045,6 +1072,17 @@ stmt := &ShowSeriesStatement{} var err error + // Parse optional ON clause. + if tok, _, _ := p.scanIgnoreWhitespace(); tok == ON { + // Parse the database. + stmt.Database, err = p.parseIdent() + if err != nil { + return nil, err + } + } else { + p.unscan() + } + // Parse optional FROM. if tok, _, _ := p.scanIgnoreWhitespace(); tok == FROM { if stmt.Sources, err = p.parseSources(); err != nil { @@ -1083,6 +1121,17 @@ stmt := &ShowMeasurementsStatement{} var err error + // Parse optional ON clause. + if tok, _, _ := p.scanIgnoreWhitespace(); tok == ON { + // Parse the database. + stmt.Database, err = p.parseIdent() + if err != nil { + return nil, err + } + } else { + p.unscan() + } + // Parse optional WITH clause. if tok, _, _ := p.scanIgnoreWhitespace(); tok == WITH { // Parse required MEASUREMENT token. @@ -1141,16 +1190,16 @@ stmt := &ShowRetentionPoliciesStatement{} // Expect an "ON" keyword. - if tok, pos, lit := p.scanIgnoreWhitespace(); tok != ON { - return nil, newParseError(tokstr(tok, lit), []string{"ON"}, pos) - } - - // Parse the database. - ident, err := p.parseIdent() - if err != nil { - return nil, err + if tok, _, _ := p.scanIgnoreWhitespace(); tok == ON { + // Parse the database. + ident, err := p.parseIdent() + if err != nil { + return nil, err + } + stmt.Database = ident + } else { + p.unscan() } - stmt.Database = ident return stmt, nil } @@ -1161,6 +1210,17 @@ stmt := &ShowTagKeysStatement{} var err error + // Parse optional ON clause. + if tok, _, _ := p.scanIgnoreWhitespace(); tok == ON { + // Parse the database. + stmt.Database, err = p.parseIdent() + if err != nil { + return nil, err + } + } else { + p.unscan() + } + // Parse optional source. if tok, _, _ := p.scanIgnoreWhitespace(); tok == FROM { if stmt.Sources, err = p.parseSources(); err != nil { @@ -1209,6 +1269,17 @@ stmt := &ShowTagValuesStatement{} var err error + // Parse optional ON clause. + if tok, _, _ := p.scanIgnoreWhitespace(); tok == ON { + // Parse the database. + stmt.Database, err = p.parseIdent() + if err != nil { + return nil, err + } + } else { + p.unscan() + } + // Parse optional source. if tok, _, _ := p.scanIgnoreWhitespace(); tok == FROM { if stmt.Sources, err = p.parseSources(); err != nil { @@ -1314,6 +1385,17 @@ stmt := &ShowFieldKeysStatement{} var err error + // Parse optional ON clause. + if tok, _, _ := p.scanIgnoreWhitespace(); tok == ON { + // Parse the database. + stmt.Database, err = p.parseIdent() + if err != nil { + return nil, err + } + } else { + p.unscan() + } + // Parse optional source. if tok, _, _ := p.scanIgnoreWhitespace(); tok == FROM { if stmt.Sources, err = p.parseSources(); err != nil { @@ -1369,6 +1451,24 @@ if stmt.Sources, err = p.parseSources(); err != nil { return nil, err } + + var err error + WalkFunc(stmt.Sources, func(n Node) { + if t, ok := n.(*Measurement); ok { + // Don't allow database or retention policy in from clause for delete + // statement. They apply to the selected database across all retention + // policies. + if t.Database != "" { + err = &ParseError{Message: "database not supported"} + } + if t.RetentionPolicy != "" { + err = &ParseError{Message: "retention policy not supported"} + } + } + }) + if err != nil { + return nil, err + } } else { p.unscan() } @@ -1852,19 +1952,27 @@ func (p *Parser) parseField() (*Field, error) { f := &Field{} - _, pos, _ := p.scanIgnoreWhitespace() - p.unscan() - // Parse the expression first. - expr, err := p.ParseExpr() + // Attempt to parse a regex. + re, err := p.parseRegex() if err != nil { return nil, err + } else if re != nil { + f.Expr = re + } else { + _, pos, _ := p.scanIgnoreWhitespace() + p.unscan() + // Parse the expression first. + expr, err := p.ParseExpr() + if err != nil { + return nil, err + } + var c validateField + Walk(&c, expr) + if c.foundInvalid { + return nil, fmt.Errorf("invalid operator %s in SELECT clause at line %d, char %d; operator is intended for WHERE clause", c.badToken, pos.Line+1, pos.Char+1) + } + f.Expr = expr } - var c validateField - Walk(&c, expr) - if c.foundInvalid { - return nil, fmt.Errorf("invalid operator %s in SELECT clause at line %d, char %d; operator is intended for WHERE clause", c.badToken, pos.Line+1, pos.Char+1) - } - f.Expr = expr // Parse the alias if the current and next tokens are "WS AS". alias, err := p.parseAlias() @@ -2052,6 +2160,13 @@ // parseDimension parses a single dimension. func (p *Parser) parseDimension() (*Dimension, error) { + re, err := p.parseRegex() + if err != nil { + return nil, err + } else if re != nil { + return &Dimension{Expr: re}, nil + } + // Parse the expression first. expr, err := p.ParseExpr() if err != nil { @@ -2081,7 +2196,7 @@ if !ok { return NullFill, nil, errors.New("fill must be a function call") } else if len(fill.Args) != 1 { - return NullFill, nil, errors.New("fill requires an argument, e.g.: 0, null, none, previous") + return NullFill, nil, errors.New("fill requires an argument, e.g.: 0, null, none, previous, linear") } switch fill.Args[0].String() { case "null": @@ -2090,6 +2205,8 @@ return NoFill, nil, nil case "previous": return PreviousFill, nil, nil + case "linear": + return LinearFill, nil, nil default: switch num := fill.Args[0].(type) { case *IntegerLiteral: @@ -2409,9 +2526,14 @@ } return &RegexLiteral{Val: re}, nil case BOUNDPARAM: - v, ok := p.params[lit] + k := strings.TrimPrefix(lit, "$") + if len(k) == 0 { + return nil, errors.New("empty bound parameter") + } + + v, ok := p.params[k] if !ok { - return nil, fmt.Errorf("missing parameter: %s", lit) + return nil, fmt.Errorf("missing parameter: %s", k) } switch v := v.(type) { @@ -2468,27 +2590,50 @@ // This function assumes the function name and LPAREN have been consumed. func (p *Parser) parseCall(name string) (*Call, error) { name = strings.ToLower(name) - // If there's a right paren then just return immediately. - if tok, _, _ := p.scan(); tok == RPAREN { - return &Call{Name: name}, nil - } - p.unscan() - // Otherwise parse function call arguments. + // Parse first function argument if one exists. var args []Expr - for { - // Parse an expression argument. + re, err := p.parseRegex() + if err != nil { + return nil, err + } else if re != nil { + args = append(args, re) + } else { + // If there's a right paren then just return immediately. + if tok, _, _ := p.scan(); tok == RPAREN { + return &Call{Name: name}, nil + } + p.unscan() + arg, err := p.ParseExpr() if err != nil { return nil, err } args = append(args, arg) + } - // If there's not a comma next then stop parsing arguments. - if tok, _, _ := p.scan(); tok != COMMA { + // Parse additional function arguments if there is a comma. + for { + // If there's not a comma, stop parsing arguments. + if tok, _, _ := p.scanIgnoreWhitespace(); tok != COMMA { p.unscan() break } + + re, err := p.parseRegex() + if err != nil { + return nil, err + } else if re != nil { + args = append(args, re) + continue + } + + // Parse an expression argument. + arg, err := p.ParseExpr() + if err != nil { + return nil, err + } + args = append(args, arg) } // There should be a right parentheses at the end. @@ -2563,6 +2708,9 @@ func (p *Parser) unscan() { p.s.Unscan() } // ParseDuration parses a time duration from a string. +// This is needed instead of time.ParseDuration because this will support +// the full syntax that InfluxQL supports for specifying durations +// including weeks and days. func ParseDuration(s string) (time.Duration, error) { // Return an error if the string is blank or one character if len(s) < 2 { @@ -2572,41 +2720,78 @@ // Split string into individual runes. a := split(s) - // Extract the unit of measure. - // If the last two characters are "ms" then parse as milliseconds. - // Otherwise just use the last character as the unit of measure. - var num, uom string - if len(s) > 2 && s[len(s)-2:] == "ms" { - num, uom = string(a[:len(a)-2]), "ms" - } else { - num, uom = string(a[:len(a)-1]), string(a[len(a)-1:]) + // Start with a zero duration. + var d time.Duration + i := 0 + + // Check for a negative. + isNegative := false + if a[i] == '-' { + isNegative = true + i++ } - // Parse the numeric part. - n, err := strconv.ParseInt(num, 10, 64) - if err != nil { - return 0, ErrInvalidDuration + var measure int64 + var unit string + + // Parsing loop. + for i < len(a) { + // Find the number portion. + start := i + for ; i < len(a) && isDigit(a[i]); i++ { + // Scan for the digits. + } + + // Check if we reached the end of the string prematurely. + if i >= len(a) || i == start { + return 0, ErrInvalidDuration + } + + // Parse the numeric part. + n, err := strconv.ParseInt(string(a[start:i]), 10, 64) + if err != nil { + return 0, ErrInvalidDuration + } + measure = n + + // Extract the unit of measure. + // If the last two characters are "ms" then parse as milliseconds. + // Otherwise just use the last character as the unit of measure. + unit = string(a[i]) + switch a[i] { + case 'u', 'µ': + d += time.Duration(n) * time.Microsecond + case 'm': + if i+1 < len(a) && a[i+1] == 's' { + unit = string(a[i : i+2]) + d += time.Duration(n) * time.Millisecond + i += 2 + continue + } + d += time.Duration(n) * time.Minute + case 's': + d += time.Duration(n) * time.Second + case 'h': + d += time.Duration(n) * time.Hour + case 'd': + d += time.Duration(n) * 24 * time.Hour + case 'w': + d += time.Duration(n) * 7 * 24 * time.Hour + default: + return 0, ErrInvalidDuration + } + i++ } - // Multiply by the unit of measure. - switch uom { - case "u", "µ": - return time.Duration(n) * time.Microsecond, nil - case "ms": - return time.Duration(n) * time.Millisecond, nil - case "s": - return time.Duration(n) * time.Second, nil - case "m": - return time.Duration(n) * time.Minute, nil - case "h": - return time.Duration(n) * time.Hour, nil - case "d": - return time.Duration(n) * 24 * time.Hour, nil - case "w": - return time.Duration(n) * 7 * 24 * time.Hour, nil - default: - return 0, ErrInvalidDuration + // Check to see if we overflowed a duration + if d < 0 && !isNegative { + return 0, fmt.Errorf("overflowed duration %d%s: choose a smaller duration or INF", measure, unit) + } + + if isNegative { + d = -d } + return d, nil } // FormatDuration formats a duration to a string. @@ -2668,7 +2853,8 @@ var buf bytes.Buffer for i, segment := range segments { needQuote := IdentNeedsQuotes(segment) || - ((i < len(segments)-1) && segment != "") // not last segment && not "" + ((i < len(segments)-1) && segment != "") || // not last segment && not "" + ((i == 0 || i == len(segments)-1) && segment == "") // the first or last segment and an empty string if needQuote { _ = buf.WriteByte('"') diff -Nru influxdb-1.0.2+dfsg1/influxql/parser_test.go influxdb-1.1.1+dfsg1/influxql/parser_test.go --- influxdb-1.0.2+dfsg1/influxql/parser_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/parser_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -170,6 +170,18 @@ }, }, + // sample + { + s: `SELECT sample(field1, 100) FROM myseries;`, + stmt: &influxql.SelectStatement{ + IsRawQuery: false, + Fields: []*influxql.Field{ + {Expr: &influxql.Call{Name: "sample", Args: []influxql.Expr{&influxql.VarRef{Val: "field1"}, &influxql.IntegerLiteral{Val: 100}}}}, + }, + Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}}, + }, + }, + // derivative { s: `SELECT derivative(field1, 1h) FROM myseries;`, @@ -329,6 +341,67 @@ }, }, }, + + // cumulative_sum + { + s: fmt.Sprintf(`SELECT cumulative_sum(field1) FROM myseries WHERE time > '%s'`, now.UTC().Format(time.RFC3339Nano)), + stmt: &influxql.SelectStatement{ + Fields: []*influxql.Field{ + { + Expr: &influxql.Call{ + Name: "cumulative_sum", + Args: []influxql.Expr{ + &influxql.VarRef{Val: "field1"}, + }, + }, + }, + }, + Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}}, + Condition: &influxql.BinaryExpr{ + Op: influxql.GT, + LHS: &influxql.VarRef{Val: "time"}, + RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)}, + }, + }, + }, + + { + s: fmt.Sprintf(`SELECT cumulative_sum(mean(field1)) FROM myseries WHERE time > '%s' GROUP BY time(1m)`, now.UTC().Format(time.RFC3339Nano)), + stmt: &influxql.SelectStatement{ + Fields: []*influxql.Field{ + { + Expr: &influxql.Call{ + Name: "cumulative_sum", + Args: []influxql.Expr{ + &influxql.Call{ + Name: "mean", + Args: []influxql.Expr{ + &influxql.VarRef{Val: "field1"}, + }, + }, + }, + }, + }, + }, + Sources: []influxql.Source{&influxql.Measurement{Name: "myseries"}}, + Dimensions: []*influxql.Dimension{ + { + Expr: &influxql.Call{ + Name: "time", + Args: []influxql.Expr{ + &influxql.DurationLiteral{Val: time.Minute}, + }, + }, + }, + }, + Condition: &influxql.BinaryExpr{ + Op: influxql.GT, + LHS: &influxql.VarRef{Val: "time"}, + RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)}, + }, + }, + }, + // holt_winters { s: fmt.Sprintf(`SELECT holt_winters(first(field1), 3, 1) FROM myseries WHERE time > '%s' GROUP BY time(1h);`, now.UTC().Format(time.RFC3339Nano)), @@ -869,6 +942,23 @@ }, }, }, + // SELECT statement with group by and multi digit duration (prevent regression from #731://github.com/influxdata/influxdb/pull/7316) + { + s: fmt.Sprintf(`SELECT count(value) FROM cpu where time < '%s' group by time(500ms)`, now.UTC().Format(time.RFC3339Nano)), + stmt: &influxql.SelectStatement{ + Fields: []*influxql.Field{{ + Expr: &influxql.Call{ + Name: "count", + Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}}}, + Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}}, + Condition: &influxql.BinaryExpr{ + Op: influxql.LT, + LHS: &influxql.VarRef{Val: "time"}, + RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)}, + }, + Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 500 * time.Millisecond}}}}}, + }, + }, // SELECT statement with fill { @@ -928,6 +1018,25 @@ }, }, + // SELECT statement with average fill + { + s: fmt.Sprintf(`SELECT mean(value) FROM cpu where time < '%s' GROUP BY time(5m) FILL(linear)`, now.UTC().Format(time.RFC3339Nano)), + stmt: &influxql.SelectStatement{ + Fields: []*influxql.Field{{ + Expr: &influxql.Call{ + Name: "mean", + Args: []influxql.Expr{&influxql.VarRef{Val: "value"}}}}}, + Sources: []influxql.Source{&influxql.Measurement{Name: "cpu"}}, + Condition: &influxql.BinaryExpr{ + Op: influxql.LT, + LHS: &influxql.VarRef{Val: "time"}, + RHS: &influxql.StringLiteral{Val: now.UTC().Format(time.RFC3339Nano)}, + }, + Dimensions: []*influxql.Dimension{{Expr: &influxql.Call{Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: 5 * time.Minute}}}}}, + Fill: influxql.LinearFill, + }, + }, + // SELECT casts { s: `SELECT field1::float, field2::integer, field3::string, field4::boolean, field5::field, tag1::tag FROM cpu`, @@ -1035,6 +1144,14 @@ }, }, + // SHOW SERIES ON db0 + { + s: `SHOW SERIES ON db0`, + stmt: &influxql.ShowSeriesStatement{ + Database: "db0", + }, + }, + // SHOW SERIES FROM // { s: `SHOW SERIES FROM /[cg]pu/`, @@ -1097,6 +1214,14 @@ }, }, + // SHOW MEASUREMENTS ON db0 + { + s: `SHOW MEASUREMENTS ON db0`, + stmt: &influxql.ShowMeasurementsStatement{ + Database: "db0", + }, + }, + // SHOW MEASUREMENTS WITH MEASUREMENT = cpu { s: `SHOW MEASUREMENTS WITH MEASUREMENT = cpu`, @@ -1140,9 +1265,15 @@ // SHOW RETENTION POLICIES { - s: `SHOW RETENTION POLICIES ON mydb`, + s: `SHOW RETENTION POLICIES`, + stmt: &influxql.ShowRetentionPoliciesStatement{}, + }, + + // SHOW RETENTION POLICIES ON db0 + { + s: `SHOW RETENTION POLICIES ON db0`, stmt: &influxql.ShowRetentionPoliciesStatement{ - Database: "mydb", + Database: "db0", }, }, @@ -1154,6 +1285,14 @@ }, }, + // SHOW TAG KEYS ON db0 + { + s: `SHOW TAG KEYS ON db0`, + stmt: &influxql.ShowTagKeysStatement{ + Database: "db0", + }, + }, + // SHOW TAG KEYS with LIMIT { s: `SHOW TAG KEYS FROM src LIMIT 2`, @@ -1357,6 +1496,16 @@ }, }, + // SHOW TAG VALUES ON db0 + { + s: `SHOW TAG VALUES ON db0 WITH KEY = "host"`, + stmt: &influxql.ShowTagValuesStatement{ + Database: "db0", + Op: influxql.EQ, + TagKeyExpr: &influxql.StringLiteral{Val: "host"}, + }, + }, + // SHOW USERS { s: `SHOW USERS`, @@ -1387,6 +1536,12 @@ }, }, }, + { + s: `SHOW FIELD KEYS ON db0`, + stmt: &influxql.ShowFieldKeysStatement{ + Database: "db0", + }, + }, // DELETE statement { @@ -2079,6 +2234,7 @@ {s: `SELECT count(value), value FROM foo`, err: `mixing aggregate and non-aggregate queries is not supported`}, {s: `SELECT count(value)/10, value FROM foo`, err: `mixing aggregate and non-aggregate queries is not supported`}, {s: `SELECT count(value) FROM foo group by time(1s)`, err: `aggregate functions with GROUP BY time require a WHERE time clause`}, + {s: `SELECT count(value) FROM foo group by time(500ms)`, err: `aggregate functions with GROUP BY time require a WHERE time clause`}, {s: `SELECT count(value) FROM foo group by time(1s) where host = 'hosta.influxdb.org'`, err: `aggregate functions with GROUP BY time require a WHERE time clause`}, {s: `SELECT count(value) FROM foo group by time`, err: `time() is a function and expects at least one argument`}, {s: `SELECT count(value) FROM foo group by 'time'`, err: `only time and tag dimensions allowed`}, @@ -2134,6 +2290,14 @@ {s: `SELECT moving_average(max(), 2) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`}, {s: `SELECT moving_average(percentile(value), 2) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`}, {s: `SELECT moving_average(mean(value), 2) FROM myseries where time < now() and time > now() - 1d`, err: `moving_average aggregate requires a GROUP BY interval`}, + {s: `SELECT cumulative_sum(), field1 FROM myseries`, err: `mixing aggregate and non-aggregate queries is not supported`}, + {s: `SELECT cumulative_sum() from myseries`, err: `invalid number of arguments for cumulative_sum, expected 1, got 0`}, + {s: `SELECT cumulative_sum(value) FROM myseries group by time(1h)`, err: `aggregate function required inside the call to cumulative_sum`}, + {s: `SELECT cumulative_sum(top(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for top, expected at least 2, got 1`}, + {s: `SELECT cumulative_sum(bottom(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for bottom, expected at least 2, got 1`}, + {s: `SELECT cumulative_sum(max()) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for max, expected 1, got 0`}, + {s: `SELECT cumulative_sum(percentile(value)) FROM myseries where time < now() and time > now() - 1d group by time(1h)`, err: `invalid number of arguments for percentile, expected 2, got 1`}, + {s: `SELECT cumulative_sum(mean(value)) FROM myseries where time < now() and time > now() - 1d`, err: `cumulative_sum aggregate requires a GROUP BY interval`}, {s: `SELECT holt_winters(value) FROM myseries where time < now() and time > now() - 1d`, err: `invalid number of arguments for holt_winters, expected 3, got 1`}, {s: `SELECT holt_winters(value, 10, 2) FROM myseries where time < now() and time > now() - 1d`, err: `must use aggregate function with holt_winters`}, {s: `SELECT holt_winters(min(value), 10, 2) FROM myseries where time < now() and time > now() - 1d`, err: `holt_winters aggregate requires a GROUP BY interval`}, @@ -2161,15 +2325,17 @@ {s: `DELETE`, err: `found EOF, expected FROM, WHERE at line 1, char 8`}, {s: `DELETE FROM`, err: `found EOF, expected identifier at line 1, char 13`}, {s: `DELETE FROM myseries WHERE`, err: `found EOF, expected identifier, string, number, bool at line 1, char 28`}, + {s: `DELETE FROM "foo".myseries`, err: `retention policy not supported at line 1, char 1`}, + {s: `DELETE FROM foo..myseries`, err: `database not supported at line 1, char 1`}, {s: `DROP MEASUREMENT`, err: `found EOF, expected identifier at line 1, char 18`}, {s: `DROP SERIES`, err: `found EOF, expected FROM, WHERE at line 1, char 13`}, {s: `DROP SERIES FROM`, err: `found EOF, expected identifier at line 1, char 18`}, {s: `DROP SERIES FROM src WHERE`, err: `found EOF, expected identifier, string, number, bool at line 1, char 28`}, + {s: `DROP SERIES FROM "foo".myseries`, err: `retention policy not supported at line 1, char 1`}, + {s: `DROP SERIES FROM foo..myseries`, err: `database not supported at line 1, char 1`}, {s: `SHOW CONTINUOUS`, err: `found EOF, expected QUERIES at line 1, char 17`}, {s: `SHOW RETENTION`, err: `found EOF, expected POLICIES at line 1, char 16`}, {s: `SHOW RETENTION ON`, err: `found ON, expected POLICIES at line 1, char 16`}, - {s: `SHOW RETENTION POLICIES`, err: `found EOF, expected ON at line 1, char 25`}, - {s: `SHOW RETENTION POLICIES mydb`, err: `found mydb, expected ON at line 1, char 25`}, {s: `SHOW RETENTION POLICIES ON`, err: `found EOF, expected identifier at line 1, char 28`}, {s: `SHOW SHARD`, err: `found EOF, expected GROUPS at line 1, char 12`}, {s: `SHOW FOO`, err: `found FOO, expected CONTINUOUS, DATABASES, DIAGNOSTICS, FIELD, GRANTS, MEASUREMENTS, QUERIES, RETENTION, SERIES, SHARD, SHARDS, STATS, SUBSCRIPTIONS, TAG, USERS at line 1, char 6`}, @@ -2301,6 +2467,8 @@ {s: `ALTER RETENTION POLICY`, err: `found EOF, expected identifier at line 1, char 24`}, {s: `ALTER RETENTION POLICY policy1`, err: `found EOF, expected ON at line 1, char 32`}, {s: `ALTER RETENTION POLICY policy1 ON`, err: `found EOF, expected identifier at line 1, char 35`}, {s: `ALTER RETENTION POLICY policy1 ON testdb`, err: `found EOF, expected DURATION, REPLICATION, SHARD, DEFAULT at line 1, char 42`}, + {s: `ALTER RETENTION POLICY policy1 ON testdb REPLICATION 1 REPLICATION 2`, err: `found duplicate REPLICATION option at line 1, char 56`}, + {s: `ALTER RETENTION POLICY policy1 ON testdb DURATION 15251w`, err: `overflowed duration 15251w: choose a smaller duration or INF at line 1, char 51`}, {s: `SET`, err: `found EOF, expected PASSWORD at line 1, char 5`}, {s: `SET PASSWORD`, err: `found EOF, expected FOR at line 1, char 14`}, {s: `SET PASSWORD something`, err: `found something, expected FOR at line 1, char 14`}, @@ -2308,6 +2476,8 @@ {s: `SET PASSWORD FOR dejan`, err: `found EOF, expected = at line 1, char 24`}, {s: `SET PASSWORD FOR dejan =`, err: `found EOF, expected string at line 1, char 25`}, {s: `SET PASSWORD FOR dejan = bla`, err: `found bla, expected string at line 1, char 26`}, + {s: `$SHOW$DATABASES`, err: `found $SHOW, expected SELECT, DELETE, SHOW, CREATE, DROP, GRANT, REVOKE, ALTER, SET, KILL at line 1, char 1`}, + {s: `SELECT * FROM cpu WHERE "tagkey" = $$`, err: `empty bound parameter`}, } for i, tt := range tests { @@ -2331,10 +2501,28 @@ if !reflect.DeepEqual(tt.err, errstring(err)) { t.Errorf("%d. %q: error mismatch:\n exp=%s\n got=%s\n\n", i, tt.s, tt.err, err) - } else if tt.err == "" && !reflect.DeepEqual(tt.stmt, stmt) { - t.Logf("\n# %s\nexp=%s\ngot=%s\n", tt.s, mustMarshalJSON(tt.stmt), mustMarshalJSON(stmt)) - t.Logf("\nSQL exp=%s\nSQL got=%s\n", tt.stmt.String(), stmt.String()) - t.Errorf("%d. %q\n\nstmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.stmt, stmt) + } else if tt.err == "" { + if !reflect.DeepEqual(tt.stmt, stmt) { + t.Logf("\n# %s\nexp=%s\ngot=%s\n", tt.s, mustMarshalJSON(tt.stmt), mustMarshalJSON(stmt)) + t.Logf("\nSQL exp=%s\nSQL got=%s\n", tt.stmt.String(), stmt.String()) + t.Errorf("%d. %q\n\nstmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.stmt, stmt) + } else { + // Attempt to reparse the statement as a string and confirm it parses the same. + // Skip this if we have some kind of statement with a password since those will never be reparsed. + switch stmt.(type) { + case *influxql.CreateUserStatement, *influxql.SetPasswordUserStatement: + continue + } + + stmt2, err := influxql.ParseStatement(stmt.String()) + if err != nil { + t.Errorf("%d. %q: unable to parse statement string: %s", i, stmt.String(), err) + } else if !reflect.DeepEqual(tt.stmt, stmt2) { + t.Logf("\n# %s\nexp=%s\ngot=%s\n", tt.s, mustMarshalJSON(tt.stmt), mustMarshalJSON(stmt2)) + t.Logf("\nSQL exp=%s\nSQL got=%s\n", tt.stmt.String(), stmt2.String()) + t.Errorf("%d. %q\n\nstmt reparse mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.stmt, stmt2) + } + } } } } @@ -2546,6 +2734,10 @@ {s: `2h`, d: 2 * time.Hour}, {s: `2d`, d: 2 * 24 * time.Hour}, {s: `2w`, d: 2 * 7 * 24 * time.Hour}, + {s: `1h30m`, d: time.Hour + 30*time.Minute}, + {s: `30ms3000u`, d: 30*time.Millisecond + 3000*time.Microsecond}, + {s: `-5s`, d: -5 * time.Second}, + {s: `-5m30s`, d: -5*time.Minute - 30*time.Second}, {s: ``, err: "invalid duration"}, {s: `3`, err: "invalid duration"}, @@ -2614,7 +2806,7 @@ ident []string s string }{ - {[]string{``}, ``}, + {[]string{``}, `""`}, {[]string{`select`}, `"select"`}, {[]string{`in-bytes`}, `"in-bytes"`}, {[]string{`foo`, `bar`}, `"foo".bar`}, @@ -2798,7 +2990,7 @@ // mustMarshalJSON encodes a value to JSON. func mustMarshalJSON(v interface{}) []byte { - b, err := json.Marshal(v) + b, err := json.MarshalIndent(v, "", " ") if err != nil { panic(err) } diff -Nru influxdb-1.0.2+dfsg1/influxql/query_executor.go influxdb-1.1.1+dfsg1/influxql/query_executor.go --- influxdb-1.0.2+dfsg1/influxql/query_executor.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/query_executor.go 2016-12-06 21:36:15.000000000 +0000 @@ -25,25 +25,22 @@ // ErrQueryInterrupted is an error returned when the query is interrupted. ErrQueryInterrupted = errors.New("query interrupted") - // ErrMaxConcurrentQueriesReached is an error when a query cannot be run - // because the maximum number of queries has been reached. - ErrMaxConcurrentQueriesReached = errors.New("max concurrent queries reached") + // ErrQueryAborted is an error returned when the query is aborted. + ErrQueryAborted = errors.New("query aborted") // ErrQueryEngineShutdown is an error sent when the query cannot be // created because the query engine was shutdown. ErrQueryEngineShutdown = errors.New("query engine shutdown") - // ErrMaxPointsReached is an error when a query hits the maximum number of - // points. - ErrMaxPointsReached = errors.New("max number of points reached") - - // ErrQueryTimeoutReached is an error when a query hits the timeout. - ErrQueryTimeoutReached = errors.New("query timeout reached") + // ErrQueryTimeoutLimitExceeded is an error when a query hits the max time allowed to run. + ErrQueryTimeoutLimitExceeded = errors.New("query-timeout limit exceeded") ) // Statistics for the QueryExecutor const ( statQueriesActive = "queriesActive" // Number of queries currently being executed + statQueriesExecuted = "queriesExecuted" // Number of queries that have been executed (started). + statQueriesFinished = "queriesFinished" // Number of queries that have finished. statQueryExecutionDuration = "queryDurationNs" // Total (wall) time spent executing queries ) @@ -53,6 +50,17 @@ // ErrMeasurementNotFound returns a measurement not found error for the given measurement name. func ErrMeasurementNotFound(name string) error { return fmt.Errorf("measurement not found: %s", name) } +// ErrMaxSelectPointsLimitExceeded is an error when a query hits the maximum number of points. +func ErrMaxSelectPointsLimitExceeded(n, limit int) error { + return fmt.Errorf("max-select-point limit exceeed: (%d/%d)", n, limit) +} + +// ErrMaxConcurrentQueriesLimitExceeded is an error when a query cannot be run +// because the maximum number of queries has been reached. +func ErrMaxConcurrentQueriesLimitExceeded(n, limit int) error { + return fmt.Errorf("max-concurrent-queries limit exceeded(%d, %d)", n, limit) +} + // ExecutionOptions contains the options for executing a query. type ExecutionOptions struct { // The database the query is running against. @@ -69,6 +77,9 @@ // Quiet suppresses non-essential output from the query executor. Quiet bool + + // AbortCh is a channel that signals when results are no longer desired by the caller. + AbortCh <-chan struct{} } // ExecutionContext contains state that the query is currently executing with. @@ -95,6 +106,30 @@ ExecutionOptions } +// send sends a Result to the Results channel and will exit if the query has +// been aborted. +func (ctx *ExecutionContext) send(result *Result) error { + select { + case <-ctx.AbortCh: + return ErrQueryAborted + case ctx.Results <- result: + } + return nil +} + +// Send sends a Result to the Results channel and will exit if the query has +// been interrupted or aborted. +func (ctx *ExecutionContext) Send(result *Result) error { + select { + case <-ctx.InterruptCh: + return ErrQueryInterrupted + case <-ctx.AbortCh: + return ErrQueryAborted + case ctx.Results <- result: + } + return nil +} + // StatementExecutor executes a statement within the QueryExecutor. type StatementExecutor interface { // ExecuteStatement executes a statement. Results should be sent to the @@ -137,6 +172,8 @@ // QueryStatistics keeps statistics related to the QueryExecutor. type QueryStatistics struct { ActiveQueries int64 + ExecutedQueries int64 + FinishedQueries int64 QueryExecutionDuration int64 } @@ -147,6 +184,8 @@ Tags: tags, Values: map[string]interface{}{ statQueriesActive: atomic.LoadInt64(&e.stats.ActiveQueries), + statQueriesExecuted: atomic.LoadInt64(&e.stats.ExecutedQueries), + statQueriesFinished: atomic.LoadInt64(&e.stats.FinishedQueries), statQueryExecutionDuration: atomic.LoadInt64(&e.stats.QueryExecutionDuration), }, }} @@ -176,14 +215,19 @@ defer e.recover(query, results) atomic.AddInt64(&e.stats.ActiveQueries, 1) + atomic.AddInt64(&e.stats.ExecutedQueries, 1) defer func(start time.Time) { atomic.AddInt64(&e.stats.ActiveQueries, -1) + atomic.AddInt64(&e.stats.FinishedQueries, 1) atomic.AddInt64(&e.stats.QueryExecutionDuration, time.Since(start).Nanoseconds()) }(time.Now()) qid, task, err := e.TaskManager.AttachQuery(query, opt.Database, closing) if err != nil { - results <- &Result{Err: err} + select { + case results <- &Result{Err: err}: + case <-opt.AbortCh: + } return } defer e.TaskManager.KillQuery(qid) @@ -254,7 +298,9 @@ // Normalize each statement if possible. if normalizer, ok := e.StatementExecutor.(StatementNormalizer); ok { if err := normalizer.NormalizeStatement(stmt, defaultDB); err != nil { - results <- &Result{Err: err} + if err := ctx.send(&Result{Err: err}); err == ErrQueryAborted { + return + } break } } @@ -276,20 +322,39 @@ // Send an error for this result if it failed for some reason. if err != nil { - results <- &Result{ + if err := ctx.send(&Result{ StatementID: i, Err: err, + }); err == ErrQueryAborted { + return } // Stop after the first error. break } + + // Check if the query was interrupted during an uninterruptible statement. + interrupted := false + if ctx.InterruptCh != nil { + select { + case <-ctx.InterruptCh: + interrupted = true + default: + // Query has not been interrupted. + } + } + + if interrupted { + break + } } // Send error results for any statements which were not executed. for ; i < len(query.Statements)-1; i++ { - results <- &Result{ + if err := ctx.send(&Result{ StatementID: i, Err: ErrNotExecuted, + }); err == ErrQueryAborted { + return } } } diff -Nru influxdb-1.0.2+dfsg1/influxql/query_executor_test.go influxdb-1.1.1+dfsg1/influxql/query_executor_test.go --- influxdb-1.0.2+dfsg1/influxql/query_executor_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/query_executor_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -3,6 +3,7 @@ import ( "errors" "fmt" + "strings" "testing" "time" @@ -110,6 +111,37 @@ } } +func TestQueryExecutor_Abort(t *testing.T) { + q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) + if err != nil { + t.Fatal(err) + } + + ch1 := make(chan struct{}) + ch2 := make(chan struct{}) + + e := NewQueryExecutor() + e.StatementExecutor = &StatementExecutor{ + ExecuteStatementFn: func(stmt influxql.Statement, ctx influxql.ExecutionContext) error { + <-ch1 + if err := ctx.Send(&influxql.Result{Err: errUnexpected}); err != influxql.ErrQueryAborted { + t.Errorf("unexpected error: %v", err) + } + close(ch2) + return nil + }, + } + + done := make(chan struct{}) + close(done) + + results := e.ExecuteQuery(q, influxql.ExecutionOptions{AbortCh: done}, nil) + close(ch1) + + <-ch2 + discardOutput(results) +} + func TestQueryExecutor_ShowQueries(t *testing.T) { q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) if err != nil { @@ -166,7 +198,7 @@ results := e.ExecuteQuery(q, influxql.ExecutionOptions{}, nil) result := <-results - if result.Err != influxql.ErrQueryTimeoutReached { + if result.Err == nil || !strings.Contains(result.Err.Error(), "query-timeout") { t.Errorf("unexpected error: %s", result.Err) } } @@ -202,7 +234,7 @@ if len(result.Series) != 0 { t.Errorf("expected %d rows, got %d", 0, len(result.Series)) } - if result.Err != influxql.ErrMaxConcurrentQueriesReached { + if result.Err == nil || !strings.Contains(result.Err.Error(), "max-concurrent-queries") { t.Errorf("unexpected error: %s", result.Err) } case <-qid: @@ -224,7 +256,6 @@ ExecuteStatementFn: func(stmt influxql.Statement, ctx influxql.ExecutionContext) error { close(ch1) <-ctx.InterruptCh - close(ch2) return influxql.ErrQueryInterrupted }, } @@ -235,6 +266,7 @@ if result.Err != influxql.ErrQueryEngineShutdown { t.Errorf("unexpected error: %s", result.Err) } + close(ch2) }(results) // Wait for the statement to start executing. @@ -247,7 +279,7 @@ select { case <-ch2: case <-time.After(100 * time.Millisecond): - t.Error("closing the query manager did not kill the query after 100 milliseconds") + t.Fatal("closing the query manager did not kill the query after 100 milliseconds") } results = e.ExecuteQuery(q, influxql.ExecutionOptions{}, nil) diff -Nru influxdb-1.0.2+dfsg1/influxql/README.md influxdb-1.1.1+dfsg1/influxql/README.md --- influxdb-1.0.2+dfsg1/influxql/README.md 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/README.md 2016-12-06 21:36:15.000000000 +0000 @@ -841,7 +841,7 @@ fields = field { "," field } . -fill_option = "null" | "none" | "previous" | int_lit | float_lit . +fill_option = "null" | "none" | "previous" | "linear" | int_lit | float_lit . host = string_lit . diff -Nru influxdb-1.0.2+dfsg1/influxql/scanner.go influxdb-1.1.1+dfsg1/influxql/scanner.go --- influxdb-1.0.2+dfsg1/influxql/scanner.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/scanner.go 2016-12-06 21:36:15.000000000 +0000 @@ -32,7 +32,7 @@ return s.scanWhitespace() } else if isLetter(ch0) || ch0 == '_' { s.r.unread() - return s.scanIdent() + return s.scanIdent(true) } else if isDigit(ch0) { return s.scanNumber() } @@ -43,7 +43,7 @@ return EOF, pos, "" case '"': s.r.unread() - return s.scanIdent() + return s.scanIdent(true) case '\'': return s.scanString() case '.': @@ -54,11 +54,11 @@ } return DOT, pos, "" case '$': - tok, _, lit := s.scanIdent() - if tok == IDENT { - tok = BOUNDPARAM + tok, _, lit = s.scanIdent(false) + if tok != IDENT { + return tok, pos, "$" + lit } - return tok, pos, lit + return BOUNDPARAM, pos, "$" + lit case '+', '-': return s.scanNumber() case '*': @@ -135,7 +135,7 @@ return WS, pos, buf.String() } -func (s *Scanner) scanIdent() (tok Token, pos Pos, lit string) { +func (s *Scanner) scanIdent(lookup bool) (tok Token, pos Pos, lit string) { // Save the starting position of the identifier. _, pos = s.r.read() s.r.unread() @@ -161,10 +161,11 @@ lit = buf.String() // If the literal matches a keyword then return that keyword. - if tok = Lookup(lit); tok != IDENT { - return tok, pos, "" + if lookup { + if tok = Lookup(lit); tok != IDENT { + return tok, pos, "" + } } - return IDENT, pos, lit } @@ -263,21 +264,32 @@ // Read as a duration or integer if it doesn't have a fractional part. if !isDecimal { - // If the next rune is a duration unit (u,µ,ms,s) then return a duration token - if ch0, _ := s.r.read(); ch0 == 'u' || ch0 == 'µ' || ch0 == 's' || ch0 == 'h' || ch0 == 'd' || ch0 == 'w' { + // If the next rune is a letter then this is a duration token. + if ch0, _ := s.r.read(); isLetter(ch0) || ch0 == 'µ' { _, _ = buf.WriteRune(ch0) - return DURATIONVAL, pos, buf.String() - } else if ch0 == 'm' { - _, _ = buf.WriteRune(ch0) - if ch1, _ := s.r.read(); ch1 == 's' { + for { + ch1, _ := s.r.read() + if !isLetter(ch1) && ch1 != 'µ' { + s.r.unread() + break + } _, _ = buf.WriteRune(ch1) - } else { - s.r.unread() + } + + // Continue reading digits and letters as part of this token. + for { + if ch0, _ := s.r.read(); isLetter(ch0) || ch0 == 'µ' || isDigit(ch0) { + _, _ = buf.WriteRune(ch0) + } else { + s.r.unread() + break + } } return DURATIONVAL, pos, buf.String() + } else { + s.r.unread() + return INTEGER, pos, buf.String() } - s.r.unread() - return INTEGER, pos, buf.String() } return NUMBER, pos, buf.String() } diff -Nru influxdb-1.0.2+dfsg1/influxql/scanner_test.go influxdb-1.1.1+dfsg1/influxql/scanner_test.go --- influxdb-1.0.2+dfsg1/influxql/scanner_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/scanner_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -70,8 +70,8 @@ {s: `"foo\"bar\""`, tok: influxql.IDENT, lit: `foo"bar"`}, {s: `test"`, tok: influxql.BADSTRING, lit: "", pos: influxql.Pos{Line: 0, Char: 3}}, {s: `"test`, tok: influxql.BADSTRING, lit: `test`}, - {s: `$host`, tok: influxql.BOUNDPARAM, lit: `host`}, - {s: `$"host param"`, tok: influxql.BOUNDPARAM, lit: `host param`}, + {s: `$host`, tok: influxql.BOUNDPARAM, lit: `$host`}, + {s: `$"host param"`, tok: influxql.BOUNDPARAM, lit: `$host param`}, {s: `true`, tok: influxql.TRUE}, {s: `false`, tok: influxql.FALSE}, @@ -108,7 +108,7 @@ {s: `10h`, tok: influxql.DURATIONVAL, lit: `10h`}, {s: `10d`, tok: influxql.DURATIONVAL, lit: `10d`}, {s: `10w`, tok: influxql.DURATIONVAL, lit: `10w`}, - {s: `10x`, tok: influxql.INTEGER, lit: `10`}, // non-duration unit + {s: `10x`, tok: influxql.DURATIONVAL, lit: `10x`}, // non-duration unit, but scanned as a duration value // Keywords {s: `ALL`, tok: influxql.ALL}, diff -Nru influxdb-1.0.2+dfsg1/influxql/select.go influxdb-1.1.1+dfsg1/influxql/select.go --- influxdb-1.0.2+dfsg1/influxql/select.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/select.go 2016-12-06 21:36:15.000000000 +0000 @@ -254,6 +254,14 @@ return nil, err } return NewIntervalIterator(input, opt), nil + case "sample": + input, err := buildExprIterator(expr.Args[0], ic, opt, selector) + if err != nil { + return nil, err + } + size := expr.Args[1].(*IntegerLiteral) + + return newSampleIterator(input, opt, int(size.Val)) case "holt_winters", "holt_winters_with_fit": input, err := buildExprIterator(expr.Args[0], ic, opt, selector) if err != nil { @@ -307,6 +315,12 @@ return newMovingAverageIterator(input, int(n.Val), opt) } panic(fmt.Sprintf("invalid series aggregate function: %s", expr.Name)) + case "cumulative_sum": + input, err := buildExprIterator(expr.Args[0], ic, opt, selector) + if err != nil { + return nil, err + } + return newCumulativeSumIterator(input, opt) default: itr, err := func() (Iterator, error) { switch expr.Name { @@ -865,30 +879,7 @@ default: return nil, fmt.Errorf("type mismatch on RHS, unable to use %T as a FloatIterator", rhs) } - return &floatExprIterator{ - left: newBufFloatIterator(left), - right: newBufFloatIterator(right), - fn: func(a *FloatPoint, b *FloatPoint) *FloatPoint { - if a != nil && b != nil { - if !a.Nil && !b.Nil { - a.Value = fn(a.Value, b.Value) - return a - } else if a.Nil { - return a - } else { - return b - } - } else if a != nil { - a.Value = float64(0) - a.Nil = true - return a - } else { - b.Value = float64(0) - b.Nil = true - return b - } - }, - }, nil + return newFloatExprIterator(left, right, opt, fn), nil case func(int64, int64) float64: left, ok := lhs.(IntegerIterator) if !ok { @@ -898,44 +889,7 @@ if !ok { return nil, fmt.Errorf("type mismatch on RHS, unable to use %T as a IntegerIterator", rhs) } - return &integerFloatExprIterator{ - left: newBufIntegerIterator(left), - right: newBufIntegerIterator(right), - fn: func(a *IntegerPoint, b *IntegerPoint) *FloatPoint { - if a == nil && b == nil { - return nil - } else if a == nil { - return &FloatPoint{ - Name: b.Name, - Tags: b.Tags, - Time: b.Time, - Aux: b.Aux, - Nil: true, - } - } else if b == nil { - return &FloatPoint{ - Name: a.Name, - Tags: a.Tags, - Time: a.Time, - Aux: a.Aux, - Nil: true, - } - } - - p := &FloatPoint{ - Name: a.Name, - Tags: a.Tags, - Time: a.Time, - Aux: a.Aux, - } - if !a.Nil && !b.Nil { - p.Value = fn(a.Value, b.Value) - } else { - p.Nil = true - } - return p - }, - }, nil + return newIntegerFloatExprIterator(left, right, opt, fn), nil case func(int64, int64) int64: left, ok := lhs.(IntegerIterator) if !ok { @@ -945,30 +899,7 @@ if !ok { return nil, fmt.Errorf("type mismatch on RHS, unable to use %T as a IntegerIterator", rhs) } - return &integerExprIterator{ - left: newBufIntegerIterator(left), - right: newBufIntegerIterator(right), - fn: func(a *IntegerPoint, b *IntegerPoint) *IntegerPoint { - if a != nil && b != nil { - if !a.Nil && !b.Nil { - a.Value = fn(a.Value, b.Value) - return a - } else if a.Nil { - return a - } else { - return b - } - } else if a != nil { - a.Value = int64(0) - a.Nil = true - return a - } else { - b.Value = int64(0) - b.Nil = true - return b - } - }, - }, nil + return newIntegerExprIterator(left, right, opt, fn), nil case func(float64, float64) bool: var left FloatIterator switch lhs := lhs.(type) { @@ -989,44 +920,7 @@ default: return nil, fmt.Errorf("type mismatch on RHS, unable to use %T as a FloatIterator", rhs) } - return &floatBooleanExprIterator{ - left: newBufFloatIterator(left), - right: newBufFloatIterator(right), - fn: func(a *FloatPoint, b *FloatPoint) *BooleanPoint { - if a == nil && b == nil { - return nil - } else if a == nil { - return &BooleanPoint{ - Name: b.Name, - Tags: b.Tags, - Time: b.Time, - Aux: b.Aux, - Nil: true, - } - } else if b == nil { - return &BooleanPoint{ - Name: a.Name, - Tags: a.Tags, - Time: a.Time, - Aux: a.Aux, - Nil: true, - } - } - - p := &BooleanPoint{ - Name: a.Name, - Tags: a.Tags, - Time: a.Time, - Aux: a.Aux, - } - if !a.Nil && !b.Nil { - p.Value = fn(a.Value, b.Value) - } else { - p.Nil = true - } - return p - }, - }, nil + return newFloatBooleanExprIterator(left, right, opt, fn), nil case func(int64, int64) bool: left, ok := lhs.(IntegerIterator) if !ok { @@ -1036,44 +930,7 @@ if !ok { return nil, fmt.Errorf("type mismatch on LHS, unable to use %T as a IntegerIterator", rhs) } - return &integerBooleanExprIterator{ - left: newBufIntegerIterator(left), - right: newBufIntegerIterator(right), - fn: func(a *IntegerPoint, b *IntegerPoint) *BooleanPoint { - if a == nil && b == nil { - return nil - } else if a == nil { - return &BooleanPoint{ - Name: b.Name, - Tags: b.Tags, - Time: b.Time, - Aux: b.Aux, - Nil: true, - } - } else if b == nil { - return &BooleanPoint{ - Name: a.Name, - Tags: a.Tags, - Time: a.Time, - Aux: a.Aux, - Nil: true, - } - } - - p := &BooleanPoint{ - Name: a.Name, - Tags: a.Tags, - Time: a.Time, - Aux: a.Aux, - } - if !a.Nil && !b.Nil { - p.Value = fn(a.Value, b.Value) - } else { - p.Nil = true - } - return p - }, - }, nil + return newIntegerBooleanExprIterator(left, right, opt, fn), nil } return nil, fmt.Errorf("unable to construct transform iterator from %T and %T", lhs, rhs) } diff -Nru influxdb-1.0.2+dfsg1/influxql/select_test.go influxdb-1.1.1+dfsg1/influxql/select_test.go --- influxdb-1.0.2+dfsg1/influxql/select_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/select_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -1133,6 +1133,119 @@ } } +// Ensure a SELECT query with a fill(linear) statement can be executed. +func TestSelect_Fill_Linear_Float_One(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return influxql.NewCallIterator(&FloatIterator{Points: []influxql.FloatPoint{ + {Name: "cpu", Tags: ParseTags("host=A"), Time: 12 * Second, Value: 2}, + {Name: "cpu", Tags: ParseTags("host=A"), Time: 32 * Second, Value: 4}, + }}, opt) + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT mean(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:01:00Z' GROUP BY host, time(10s) fill(linear)`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Nil: true}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: 2, Aggregated: 1}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 20 * Second, Value: 3}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 30 * Second, Value: 4, Aggregated: 1}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 40 * Second, Nil: true}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 50 * Second, Nil: true}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +func TestSelect_Fill_Linear_Float_Many(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return influxql.NewCallIterator(&FloatIterator{Points: []influxql.FloatPoint{ + {Name: "cpu", Tags: ParseTags("host=A"), Time: 12 * Second, Value: 2}, + {Name: "cpu", Tags: ParseTags("host=A"), Time: 62 * Second, Value: 7}, + }}, opt) + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT mean(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:01:00Z' GROUP BY host, time(10s) fill(linear)`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Nil: true}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: 2, Aggregated: 1}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 20 * Second, Value: 3}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 30 * Second, Value: 4}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 40 * Second, Value: 5}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 50 * Second, Value: 6}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 60 * Second, Value: 7, Aggregated: 1}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +// Ensure a SELECT query with a fill(linear) statement can be executed for integers. +func TestSelect_Fill_Linear_Integer_One(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return influxql.NewCallIterator(&IntegerIterator{Points: []influxql.IntegerPoint{ + {Name: "cpu", Tags: ParseTags("host=A"), Time: 12 * Second, Value: 1}, + {Name: "cpu", Tags: ParseTags("host=A"), Time: 32 * Second, Value: 4}, + }}, opt) + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT max(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:01:00Z' GROUP BY host, time(10s) fill(linear)`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Nil: true}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: 1, Aggregated: 1}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 20 * Second, Value: 2}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 30 * Second, Value: 4, Aggregated: 1}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 40 * Second, Nil: true}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 50 * Second, Nil: true}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +func TestSelect_Fill_Linear_Integer_Many(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return influxql.NewCallIterator(&IntegerIterator{Points: []influxql.IntegerPoint{ + {Name: "cpu", Tags: ParseTags("host=A"), Time: 12 * Second, Value: 1}, + {Name: "cpu", Tags: ParseTags("host=A"), Time: 72 * Second, Value: 10}, + }}, opt) + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT max(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:01:20Z' GROUP BY host, time(10s) fill(linear)`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Nil: true}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: 1, Aggregated: 1}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 20 * Second, Value: 2}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 30 * Second, Value: 4}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 40 * Second, Value: 5}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 50 * Second, Value: 7}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 60 * Second, Value: 8}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 70 * Second, Value: 10, Aggregated: 1}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + // Ensure a SELECT stddev() query can be executed. func TestSelect_Stddev_Float(t *testing.T) { var ic IteratorCreator @@ -1207,43 +1320,6 @@ } } -// Ensure a SELECT stddev() query can be executed. -func TestSelect_Stddev_String(t *testing.T) { - var ic IteratorCreator - ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { - return &StringIterator{Points: []influxql.StringPoint{ - {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 0 * Second, Value: "a"}, - {Name: "cpu", Tags: ParseTags("region=west,host=B"), Time: 5 * Second, Value: "b"}, - {Name: "cpu", Tags: ParseTags("region=east,host=A"), Time: 9 * Second, Value: "c"}, - {Name: "cpu", Tags: ParseTags("region=east,host=A"), Time: 10 * Second, Value: "d"}, - {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 11 * Second, Value: "e"}, - {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 31 * Second, Value: "f"}, - - {Name: "cpu", Tags: ParseTags("region=west,host=B"), Time: 50 * Second, Value: "g"}, - {Name: "cpu", Tags: ParseTags("region=west,host=B"), Time: 51 * Second, Value: "h"}, - {Name: "cpu", Tags: ParseTags("region=west,host=B"), Time: 52 * Second, Value: "i"}, - {Name: "cpu", Tags: ParseTags("region=west,host=B"), Time: 53 * Second, Value: "j"}, - {Name: "cpu", Tags: ParseTags("region=west,host=B"), Time: 53 * Second, Value: "k"}, - }}, nil - } - - // Execute selection. - itrs, err := influxql.Select(MustParseSelectStatement(`SELECT stddev(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-02T00:00:00Z' GROUP BY time(10s), host fill(none)`), &ic, nil) - if err != nil { - t.Fatal(err) - } else if a, err := Iterators(itrs).ReadAll(); err != nil { - t.Fatalf("unexpected error: %s", err) - } else if !deep.Equal(a, [][]influxql.Point{ - {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: ""}}, - {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 0 * Second, Value: ""}}, - {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: ""}}, - {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 30 * Second, Value: ""}}, - {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 50 * Second, Value: ""}}, - }) { - t.Fatalf("unexpected points: %s", spew.Sdump(a)) - } -} - // Ensure a SELECT spread() query can be executed. func TestSelect_Spread_Float(t *testing.T) { var ic IteratorCreator @@ -1402,6 +1478,118 @@ } } +// Ensure a SELECT sample() query can be executed. +func TestSelect_Sample_Float(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &FloatIterator{Points: []influxql.FloatPoint{ + {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 0 * Second, Value: 20}, + {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 5 * Second, Value: 10}, + {Name: "cpu", Tags: ParseTags("region=east,host=B"), Time: 10 * Second, Value: 19}, + {Name: "cpu", Tags: ParseTags("region=east,host=B"), Time: 15 * Second, Value: 2}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT sample(value, 2) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-02T00:00:00Z' GROUP BY time(10s), host fill(none)`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: 20}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 5 * Second, Value: 10}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 10 * Second, Value: 19}}, + {&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 15 * Second, Value: 2}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +// Ensure a SELECT sample() query can be executed. +func TestSelect_Sample_Integer(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &IntegerIterator{Points: []influxql.IntegerPoint{ + {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 0 * Second, Value: 20}, + {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 5 * Second, Value: 10}, + {Name: "cpu", Tags: ParseTags("region=east,host=B"), Time: 10 * Second, Value: 19}, + {Name: "cpu", Tags: ParseTags("region=east,host=B"), Time: 15 * Second, Value: 2}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT sample(value, 2) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-02T00:00:00Z' GROUP BY time(10s), host fill(none)`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: 20}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 5 * Second, Value: 10}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 10 * Second, Value: 19}}, + {&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 15 * Second, Value: 2}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +// Ensure a SELECT sample() query can be executed. +func TestSelect_Sample_Boolean(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &BooleanIterator{Points: []influxql.BooleanPoint{ + {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 0 * Second, Value: true}, + {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 5 * Second, Value: false}, + {Name: "cpu", Tags: ParseTags("region=east,host=B"), Time: 10 * Second, Value: false}, + {Name: "cpu", Tags: ParseTags("region=east,host=B"), Time: 15 * Second, Value: true}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT sample(value, 2) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-02T00:00:00Z' GROUP BY time(10s), host fill(none)`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: true}}, + {&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 5 * Second, Value: false}}, + {&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 10 * Second, Value: false}}, + {&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 15 * Second, Value: true}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +// Ensure a SELECT sample() query can be executed. +func TestSelect_Sample_String(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &StringIterator{Points: []influxql.StringPoint{ + {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 0 * Second, Value: "a"}, + {Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 5 * Second, Value: "b"}, + {Name: "cpu", Tags: ParseTags("region=east,host=B"), Time: 10 * Second, Value: "c"}, + {Name: "cpu", Tags: ParseTags("region=east,host=B"), Time: 15 * Second, Value: "d"}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT sample(value, 2) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-02T00:00:00Z' GROUP BY time(10s), host fill(none)`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: "a"}}, + {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 5 * Second, Value: "b"}}, + {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 10 * Second, Value: "c"}}, + {&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 15 * Second, Value: "d"}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + // Ensure a simple raw SELECT statement can be executed. func TestSelect_Raw(t *testing.T) { // Mock two iterators -- one for each value in the query. @@ -2507,6 +2695,114 @@ }) { t.Fatalf("unexpected points: %s", spew.Sdump(a)) } +} + +func TestSelect_CumulativeSum_Float(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &FloatIterator{Points: []influxql.FloatPoint{ + {Name: "cpu", Time: 0 * Second, Value: 20}, + {Name: "cpu", Time: 4 * Second, Value: 10}, + {Name: "cpu", Time: 8 * Second, Value: 19}, + {Name: "cpu", Time: 12 * Second, Value: 3}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT cumulative_sum(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:00:16Z'`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.FloatPoint{Name: "cpu", Time: 0 * Second, Value: 20}}, + {&influxql.FloatPoint{Name: "cpu", Time: 4 * Second, Value: 30}}, + {&influxql.FloatPoint{Name: "cpu", Time: 8 * Second, Value: 49}}, + {&influxql.FloatPoint{Name: "cpu", Time: 12 * Second, Value: 52}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +func TestSelect_CumulativeSum_Integer(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &IntegerIterator{Points: []influxql.IntegerPoint{ + {Name: "cpu", Time: 0 * Second, Value: 20}, + {Name: "cpu", Time: 4 * Second, Value: 10}, + {Name: "cpu", Time: 8 * Second, Value: 19}, + {Name: "cpu", Time: 12 * Second, Value: 3}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT cumulative_sum(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:00:16Z'`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.IntegerPoint{Name: "cpu", Time: 0 * Second, Value: 20}}, + {&influxql.IntegerPoint{Name: "cpu", Time: 4 * Second, Value: 30}}, + {&influxql.IntegerPoint{Name: "cpu", Time: 8 * Second, Value: 49}}, + {&influxql.IntegerPoint{Name: "cpu", Time: 12 * Second, Value: 52}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +func TestSelect_CumulativeSum_Duplicate_Float(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &FloatIterator{Points: []influxql.FloatPoint{ + {Name: "cpu", Time: 0 * Second, Value: 20}, + {Name: "cpu", Time: 0 * Second, Value: 19}, + {Name: "cpu", Time: 4 * Second, Value: 10}, + {Name: "cpu", Time: 4 * Second, Value: 3}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT cumulative_sum(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:00:16Z'`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.FloatPoint{Name: "cpu", Time: 0 * Second, Value: 20}}, + {&influxql.FloatPoint{Name: "cpu", Time: 0 * Second, Value: 39}}, + {&influxql.FloatPoint{Name: "cpu", Time: 4 * Second, Value: 49}}, + {&influxql.FloatPoint{Name: "cpu", Time: 4 * Second, Value: 52}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } +} + +func TestSelect_CumulativeSum_Duplicate_Integer(t *testing.T) { + var ic IteratorCreator + ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) { + return &IntegerIterator{Points: []influxql.IntegerPoint{ + {Name: "cpu", Time: 0 * Second, Value: 20}, + {Name: "cpu", Time: 0 * Second, Value: 19}, + {Name: "cpu", Time: 4 * Second, Value: 10}, + {Name: "cpu", Time: 4 * Second, Value: 3}, + }}, nil + } + + // Execute selection. + itrs, err := influxql.Select(MustParseSelectStatement(`SELECT cumulative_sum(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-01T00:00:16Z'`), &ic, nil) + if err != nil { + t.Fatal(err) + } else if a, err := Iterators(itrs).ReadAll(); err != nil { + t.Fatalf("unexpected error: %s", err) + } else if !deep.Equal(a, [][]influxql.Point{ + {&influxql.IntegerPoint{Name: "cpu", Time: 0 * Second, Value: 20}}, + {&influxql.IntegerPoint{Name: "cpu", Time: 0 * Second, Value: 39}}, + {&influxql.IntegerPoint{Name: "cpu", Time: 4 * Second, Value: 49}}, + {&influxql.IntegerPoint{Name: "cpu", Time: 4 * Second, Value: 52}}, + }) { + t.Fatalf("unexpected points: %s", spew.Sdump(a)) + } } func TestSelect_HoltWinters_GroupBy_Agg(t *testing.T) { diff -Nru influxdb-1.0.2+dfsg1/influxql/statement_rewriter.go influxdb-1.1.1+dfsg1/influxql/statement_rewriter.go --- influxdb-1.0.2+dfsg1/influxql/statement_rewriter.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/statement_rewriter.go 2016-12-06 21:36:15.000000000 +0000 @@ -26,7 +26,7 @@ {Expr: &VarRef{Val: "fieldKey"}}, {Expr: &VarRef{Val: "fieldType"}}, }), - Sources: rewriteSources(stmt.Sources, "_fieldKeys"), + Sources: rewriteSources(stmt.Sources, "_fieldKeys", stmt.Database), Condition: rewriteSourcesCondition(stmt.Sources, nil), Offset: stmt.Offset, Limit: stmt.Limit, @@ -47,6 +47,7 @@ condition = rewriteSourcesCondition(Sources([]Source{stmt.Source}), stmt.Condition) } return &ShowMeasurementsStatement{ + Database: stmt.Database, Condition: condition, Limit: stmt.Limit, Offset: stmt.Offset, @@ -64,7 +65,7 @@ Fields: []*Field{ {Expr: &VarRef{Val: "key"}}, }, - Sources: rewriteSources(stmt.Sources, "_series"), + Sources: rewriteSources(stmt.Sources, "_series", stmt.Database), Condition: rewriteSourcesCondition(stmt.Sources, stmt.Condition), Offset: stmt.Offset, Limit: stmt.Limit, @@ -121,6 +122,7 @@ condition = rewriteSourcesCondition(stmt.Sources, condition) return &ShowTagValuesStatement{ + Database: stmt.Database, Op: stmt.Op, TagKeyExpr: stmt.TagKeyExpr, Condition: condition, @@ -140,7 +142,7 @@ Fields: []*Field{ {Expr: &VarRef{Val: "tagKey"}}, }, - Sources: rewriteSources(stmt.Sources, "_tagKeys"), + Sources: rewriteSources(stmt.Sources, "_tagKeys", stmt.Database), Condition: rewriteSourcesCondition(stmt.Sources, stmt.Condition), Offset: stmt.Offset, Limit: stmt.Limit, @@ -151,22 +153,29 @@ } // rewriteSources rewrites sources with previous database and retention policy -func rewriteSources(sources Sources, measurementName string) Sources { +func rewriteSources(sources Sources, measurementName, defaultDatabase string) Sources { newSources := Sources{} for _, src := range sources { if src == nil { continue } mm := src.(*Measurement) + database := mm.Database + if database == "" { + database = defaultDatabase + } newSources = append(newSources, &Measurement{ - Database: mm.Database, + Database: database, RetentionPolicy: mm.RetentionPolicy, Name: measurementName, }) } if len(newSources) <= 0 { - return append(newSources, &Measurement{Name: measurementName}) + return append(newSources, &Measurement{ + Database: defaultDatabase, + Name: measurementName, + }) } return newSources } diff -Nru influxdb-1.0.2+dfsg1/influxql/statement_rewriter_test.go influxdb-1.1.1+dfsg1/influxql/statement_rewriter_test.go --- influxdb-1.0.2+dfsg1/influxql/statement_rewriter_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/statement_rewriter_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -16,66 +16,130 @@ s: `SELECT fieldKey, fieldType FROM _fieldKeys`, }, { + stmt: `SHOW FIELD KEYS ON db0`, + s: `SELECT fieldKey, fieldType FROM db0.._fieldKeys`, + }, + { stmt: `SHOW FIELD KEYS FROM cpu`, s: `SELECT fieldKey, fieldType FROM _fieldKeys WHERE _name = 'cpu'`, }, { + stmt: `SHOW FIELD KEYS ON db0 FROM cpu`, + s: `SELECT fieldKey, fieldType FROM db0.._fieldKeys WHERE _name = 'cpu'`, + }, + { stmt: `SHOW FIELD KEYS FROM /c.*/`, s: `SELECT fieldKey, fieldType FROM _fieldKeys WHERE _name =~ /c.*/`, }, { + stmt: `SHOW FIELD KEYS ON db0 FROM /c.*/`, + s: `SELECT fieldKey, fieldType FROM db0.._fieldKeys WHERE _name =~ /c.*/`, + }, + { stmt: `SHOW FIELD KEYS FROM mydb.myrp2.cpu`, s: `SELECT fieldKey, fieldType FROM mydb.myrp2._fieldKeys WHERE _name = 'cpu'`, }, { + stmt: `SHOW FIELD KEYS ON db0 FROM mydb.myrp2.cpu`, + s: `SELECT fieldKey, fieldType FROM mydb.myrp2._fieldKeys WHERE _name = 'cpu'`, + }, + { stmt: `SHOW FIELD KEYS FROM mydb.myrp2./c.*/`, s: `SELECT fieldKey, fieldType FROM mydb.myrp2._fieldKeys WHERE _name =~ /c.*/`, }, { + stmt: `SHOW FIELD KEYS ON db0 FROM mydb.myrp2./c.*/`, + s: `SELECT fieldKey, fieldType FROM mydb.myrp2._fieldKeys WHERE _name =~ /c.*/`, + }, + { stmt: `SHOW SERIES`, s: `SELECT "key" FROM _series`, }, { + stmt: `SHOW SERIES ON db0`, + s: `SELECT "key" FROM db0.._series`, + }, + { stmt: `SHOW SERIES FROM cpu`, s: `SELECT "key" FROM _series WHERE _name = 'cpu'`, }, { + stmt: `SHOW SERIES ON db0 FROM cpu`, + s: `SELECT "key" FROM db0.._series WHERE _name = 'cpu'`, + }, + { stmt: `SHOW SERIES FROM mydb.myrp1.cpu`, s: `SELECT "key" FROM mydb.myrp1._series WHERE _name = 'cpu'`, }, { + stmt: `SHOW SERIES ON db0 FROM mydb.myrp1.cpu`, + s: `SELECT "key" FROM mydb.myrp1._series WHERE _name = 'cpu'`, + }, + { stmt: `SHOW SERIES FROM mydb.myrp1./c.*/`, s: `SELECT "key" FROM mydb.myrp1._series WHERE _name =~ /c.*/`, }, { + stmt: `SHOW SERIES ON db0 FROM mydb.myrp1./c.*/`, + s: `SELECT "key" FROM mydb.myrp1._series WHERE _name =~ /c.*/`, + }, + { stmt: `SHOW TAG KEYS`, s: `SELECT tagKey FROM _tagKeys`, }, { + stmt: `SHOW TAG KEYS ON db0`, + s: `SELECT tagKey FROM db0.._tagKeys`, + }, + { stmt: `SHOW TAG KEYS FROM cpu`, s: `SELECT tagKey FROM _tagKeys WHERE _name = 'cpu'`, }, { + stmt: `SHOW TAG KEYS ON db0 FROM cpu`, + s: `SELECT tagKey FROM db0.._tagKeys WHERE _name = 'cpu'`, + }, + { stmt: `SHOW TAG KEYS FROM /c.*/`, s: `SELECT tagKey FROM _tagKeys WHERE _name =~ /c.*/`, }, { + stmt: `SHOW TAG KEYS ON db0 FROM /c.*/`, + s: `SELECT tagKey FROM db0.._tagKeys WHERE _name =~ /c.*/`, + }, + { stmt: `SHOW TAG KEYS FROM cpu WHERE region = 'uswest'`, s: `SELECT tagKey FROM _tagKeys WHERE (_name = 'cpu') AND (region = 'uswest')`, }, { + stmt: `SHOW TAG KEYS ON db0 FROM cpu WHERE region = 'uswest'`, + s: `SELECT tagKey FROM db0.._tagKeys WHERE (_name = 'cpu') AND (region = 'uswest')`, + }, + { stmt: `SHOW TAG KEYS FROM mydb.myrp1.cpu`, s: `SELECT tagKey FROM mydb.myrp1._tagKeys WHERE _name = 'cpu'`, }, { + stmt: `SHOW TAG KEYS ON db0 FROM mydb.myrp1.cpu`, + s: `SELECT tagKey FROM mydb.myrp1._tagKeys WHERE _name = 'cpu'`, + }, + { stmt: `SHOW TAG KEYS FROM mydb.myrp1./c.*/`, s: `SELECT tagKey FROM mydb.myrp1._tagKeys WHERE _name =~ /c.*/`, }, { + stmt: `SHOW TAG KEYS ON db0 FROM mydb.myrp1./c.*/`, + s: `SELECT tagKey FROM mydb.myrp1._tagKeys WHERE _name =~ /c.*/`, + }, + { stmt: `SHOW TAG KEYS FROM mydb.myrp1.cpu WHERE region = 'uswest'`, s: `SELECT tagKey FROM mydb.myrp1._tagKeys WHERE (_name = 'cpu') AND (region = 'uswest')`, }, { + stmt: `SHOW TAG KEYS ON db0 FROM mydb.myrp1.cpu WHERE region = 'uswest'`, + s: `SELECT tagKey FROM mydb.myrp1._tagKeys WHERE (_name = 'cpu') AND (region = 'uswest')`, + }, + { stmt: `SELECT value FROM cpu`, s: `SELECT value FROM cpu`, }, diff -Nru influxdb-1.0.2+dfsg1/influxql/task_manager.go influxdb-1.1.1+dfsg1/influxql/task_manager.go --- influxdb-1.0.2+dfsg1/influxql/task_manager.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/influxql/task_manager.go 2016-12-06 21:36:15.000000000 +0000 @@ -95,15 +95,16 @@ for id, qi := range t.queries { d := now.Sub(qi.startTime) - var ds string - if d == 0 { - ds = "0s" - } else if d < time.Second { - ds = fmt.Sprintf("%du", d) - } else { - ds = (d - (d % time.Second)).String() + switch { + case d >= time.Second: + d = d - (d % time.Second) + case d >= time.Millisecond: + d = d - (d % time.Millisecond) + case d >= time.Microsecond: + d = d - (d % time.Microsecond) } - values = append(values, []interface{}{id, qi.query, qi.database, ds}) + + values = append(values, []interface{}{id, qi.query, qi.database, d.String()}) } return []*models.Row{{ @@ -135,7 +136,7 @@ } if t.MaxConcurrentQueries > 0 && len(t.queries) >= t.MaxConcurrentQueries { - return 0, nil, ErrMaxConcurrentQueriesReached + return 0, nil, ErrMaxConcurrentQueriesLimitExceeded(len(t.queries), t.MaxConcurrentQueries) } qid := t.nextID @@ -239,7 +240,7 @@ if !ok { break } - query.setError(ErrQueryTimeoutReached) + query.setError(ErrQueryTimeoutLimitExceeded) case <-interrupt: // Query was manually closed so exit the select. return diff -Nru influxdb-1.0.2+dfsg1/internal/meta_client.go influxdb-1.1.1+dfsg1/internal/meta_client.go --- influxdb-1.0.2+dfsg1/internal/meta_client.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/internal/meta_client.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,162 @@ +package internal + +import ( + "time" + + "github.com/influxdata/influxdb/influxql" + "github.com/influxdata/influxdb/services/meta" +) + +// MetaClientMock is a mockable implementation of meta.MetaClient. +type MetaClientMock struct { + CloseFn func() error + CreateContinuousQueryFn func(database, name, query string) error + CreateDatabaseFn func(name string) (*meta.DatabaseInfo, error) + CreateDatabaseWithRetentionPolicyFn func(name string, spec *meta.RetentionPolicySpec) (*meta.DatabaseInfo, error) + CreateRetentionPolicyFn func(database string, spec *meta.RetentionPolicySpec) (*meta.RetentionPolicyInfo, error) + CreateShardGroupFn func(database, policy string, timestamp time.Time) (*meta.ShardGroupInfo, error) + CreateSubscriptionFn func(database, rp, name, mode string, destinations []string) error + CreateUserFn func(name, password string, admin bool) (*meta.UserInfo, error) + + DatabaseFn func(name string) *meta.DatabaseInfo + DatabasesFn func() []meta.DatabaseInfo + + DataFn func() meta.Data + DeleteShardGroupFn func(database string, policy string, id uint64) error + DropContinuousQueryFn func(database, name string) error + DropDatabaseFn func(name string) error + DropRetentionPolicyFn func(database, name string) error + DropSubscriptionFn func(database, rp, name string) error + DropShardFn func(id uint64) error + DropUserFn func(name string) error + + OpenFn func() error + + RetentionPolicyFn func(database, name string) (rpi *meta.RetentionPolicyInfo, err error) + + SetAdminPrivilegeFn func(username string, admin bool) error + SetDataFn func(*meta.Data) error + SetDefaultRetentionPolicyFn func(database, name string) error + SetPrivilegeFn func(username, database string, p influxql.Privilege) error + ShardsByTimeRangeFn func(sources influxql.Sources, tmin, tmax time.Time) (a []meta.ShardInfo, err error) + ShardOwnerFn func(shardID uint64) (database, policy string, sgi *meta.ShardGroupInfo) + UpdateRetentionPolicyFn func(database, name string, rpu *meta.RetentionPolicyUpdate) error + UpdateUserFn func(name, password string) error + UserPrivilegeFn func(username, database string) (*influxql.Privilege, error) + UserPrivilegesFn func(username string) (map[string]influxql.Privilege, error) + UsersFn func() []meta.UserInfo +} + +func (c *MetaClientMock) Close() error { + return c.CloseFn() +} + +func (c *MetaClientMock) CreateContinuousQuery(database, name, query string) error { + return c.CreateContinuousQueryFn(database, name, query) +} + +func (c *MetaClientMock) CreateDatabase(name string) (*meta.DatabaseInfo, error) { + return c.CreateDatabaseFn(name) +} + +func (c *MetaClientMock) CreateDatabaseWithRetentionPolicy(name string, spec *meta.RetentionPolicySpec) (*meta.DatabaseInfo, error) { + return c.CreateDatabaseWithRetentionPolicyFn(name, spec) +} + +func (c *MetaClientMock) CreateRetentionPolicy(database string, spec *meta.RetentionPolicySpec) (*meta.RetentionPolicyInfo, error) { + return c.CreateRetentionPolicyFn(database, spec) +} + +func (c *MetaClientMock) CreateShardGroup(database, policy string, timestamp time.Time) (*meta.ShardGroupInfo, error) { + return c.CreateShardGroupFn(database, policy, timestamp) +} + +func (c *MetaClientMock) CreateSubscription(database, rp, name, mode string, destinations []string) error { + return c.CreateSubscriptionFn(database, rp, name, mode, destinations) +} + +func (c *MetaClientMock) CreateUser(name, password string, admin bool) (*meta.UserInfo, error) { + return c.CreateUserFn(name, password, admin) +} + +func (c *MetaClientMock) Database(name string) *meta.DatabaseInfo { + return c.DatabaseFn(name) +} + +func (c *MetaClientMock) Databases() []meta.DatabaseInfo { + return c.DatabasesFn() +} + +func (c *MetaClientMock) DeleteShardGroup(database string, policy string, id uint64) error { + return c.DeleteShardGroup(database, policy, id) +} + +func (c *MetaClientMock) DropContinuousQuery(database, name string) error { + return c.DropContinuousQueryFn(database, name) +} + +func (c *MetaClientMock) DropDatabase(name string) error { + return c.DropDatabaseFn(name) +} + +func (c *MetaClientMock) DropRetentionPolicy(database, name string) error { + return c.DropRetentionPolicyFn(database, name) +} + +func (c *MetaClientMock) DropShard(id uint64) error { + return c.DropShardFn(id) +} + +func (c *MetaClientMock) DropSubscription(database, rp, name string) error { + return c.DropSubscriptionFn(database, rp, name) +} + +func (c *MetaClientMock) DropUser(name string) error { + return c.DropUserFn(name) +} + +func (c *MetaClientMock) RetentionPolicy(database, name string) (rpi *meta.RetentionPolicyInfo, err error) { + return c.RetentionPolicyFn(database, name) +} + +func (c *MetaClientMock) SetAdminPrivilege(username string, admin bool) error { + return c.SetAdminPrivilegeFn(username, admin) +} + +func (c *MetaClientMock) SetDefaultRetentionPolicy(database, name string) error { + return c.SetDefaultRetentionPolicyFn(database, name) +} + +func (c *MetaClientMock) SetPrivilege(username, database string, p influxql.Privilege) error { + return c.SetPrivilegeFn(username, database, p) +} + +func (c *MetaClientMock) ShardsByTimeRange(sources influxql.Sources, tmin, tmax time.Time) (a []meta.ShardInfo, err error) { + return c.ShardsByTimeRangeFn(sources, tmin, tmax) +} + +func (c *MetaClientMock) ShardOwner(shardID uint64) (database, policy string, sgi *meta.ShardGroupInfo) { + return c.ShardOwnerFn(shardID) +} + +func (c *MetaClientMock) UpdateRetentionPolicy(database, name string, rpu *meta.RetentionPolicyUpdate) error { + return c.UpdateRetentionPolicyFn(database, name, rpu) +} + +func (c *MetaClientMock) UpdateUser(name, password string) error { + return c.UpdateUserFn(name, password) +} + +func (c *MetaClientMock) UserPrivilege(username, database string) (*influxql.Privilege, error) { + return c.UserPrivilegeFn(username, database) +} + +func (c *MetaClientMock) UserPrivileges(username string) (map[string]influxql.Privilege, error) { + return c.UserPrivilegesFn(username) +} + +func (c *MetaClientMock) Users() []meta.UserInfo { return c.UsersFn() } + +func (c *MetaClientMock) Open() error { return c.OpenFn() } +func (c *MetaClientMock) Data() meta.Data { return c.DataFn() } +func (c *MetaClientMock) SetData(d *meta.Data) error { return c.SetDataFn(d) } diff -Nru influxdb-1.0.2+dfsg1/man/influx_inspect.txt influxdb-1.1.1+dfsg1/man/influx_inspect.txt --- influxdb-1.0.2+dfsg1/man/influx_inspect.txt 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/man/influx_inspect.txt 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,77 @@ +influx_inspect(1) +================= + +NAME +---- +influx_inspect - Displays detailed information about InfluxDB data files + +SYNPOSIS +-------- +[verse] +'influx_inspect dumptsm' [options] +'influx_inspect export' [options] +'influx_inspect report' [options] + +DESCRIPTION +----------- +Displays detailed information about InfluxDB data files through one of the +following commands. + +*dumptsm*:: + Dumps low-level details about tsm1 files. + +*export*:: + Exports TSM files into InfluxDB line protocol format. + +*report*:: + Displays shard level report. + +DUMPTSM OPTIONS +--------------- +-all:: + Dump all data. Caution: This may print a lot of information. + +-blocks:: + Dump raw block data. + +-filter-key :: + Only display index and block data that match this key substring. + +-index:: + Dump raw index data. + +EXPORT OPTIONS +-------------- +-compress:: + Compress the output. + +-db :: + The database to export. Optional. + +-rp :: + The retention policy to export. Optional. Requires the '-db ' option to be specified. + +-data-dir :: + Data storage path. Defaults to '~/.influxdb/data'. + +-wal-dir :: + Wal storage path. Defaults to '~/.influxdb/wal'. + +-start :: + The start time of the export. The timestamp is in RFC3339 format. Optional. + +-end :: + The end time of the export. The timestamp is in RFC3339 format. Optional. + +-out :: + Destination file to write exported data to. Defaults to '~/.influxdb/export'. + +REPORT OPTIONS +-------------- +-detailed:: + Report detailed cardinality estimates. + +-pattern :: + Include only files matching a pattern. + +include:footer.txt[] diff -Nru influxdb-1.0.2+dfsg1/man/influx_stress.txt influxdb-1.1.1+dfsg1/man/influx_stress.txt --- influxdb-1.0.2+dfsg1/man/influx_stress.txt 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/man/influx_stress.txt 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,52 @@ +influx_stress(1) +================ + +NAME +---- +influx_stress - Runs a stress test against one or multiple InfluxDB servers + +SYNOPSIS +-------- +[verse] +'influx_stress' [options] + +DESCRIPTION +----------- +Runs write and query stress tests against one or multiple InfluxDB servers to +create reproducible performance benchmarks against InfluxDB. + +OPTIONS +------- +-addr :: + IP address and port of the database where response times will persist. This + is not for specifying which database to test against. That option is located + inside of the configuration file. The default is 'http://localhost:8086'. + +-database :: + The database where response times will persist. This is not for specifying + which database to test against. See '-db' or the configuration file for that + option. The default is 'stress'. + +-retention-policy :: + The retention policy where response times will persist. This is not for + specifying which retention policy to test against. See the configuration file + for that option. The default is an empty string which will use the default + retention policy. + +-config :: + The stress configuration file. + +-cpuprofile :: + Write the cpu profile to the path. No cpu profile is written unless this is + used. This profiles 'influx_stress', not the InfluxDB server. + +-db :: + The target database within the test system for write and query load. + +-tags :: + A comma separated list of tags. + +-v2:: + Use version 2 of the stress tool. The default is to use version 1. + +include::footer.txt[] diff -Nru influxdb-1.0.2+dfsg1/man/influx_tsm.txt influxdb-1.1.1+dfsg1/man/influx_tsm.txt --- influxdb-1.0.2+dfsg1/man/influx_tsm.txt 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/man/influx_tsm.txt 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,58 @@ +influx_tsm(1) +============= + +NAME +---- +influx_tsm - Convert a database from b1 or bz1 format to tsm1 format + +SYNPOSIS +-------- +[verse] +'influx_tsm' [options] + +DESCRIPTION +----------- +This tool can be used to convert a database from the deprecated b1 or bz1 +formats to tsm1 format. The b1 and bz1 formats were deprecated in 0.10 and +removed in 0.12. + +This tool will backup the directories before conversion (if not disabled). The +backed-up files must be removed manually, generally after starting up the node +again to make sure all of the data has been converted correctly. + +To restore a backup after attempting to convert to tsm1, you shut down the +node, remove the converted directory, and copy the backed-up directory to the +original location. + +OPTIONS +------- +-backup :: + The location to backup the current databases. Must not be within the data + directory. + +-dbs :: + Comma-delimited list of databases to convert. The default is to convert all + databases. + +-debug :: + If set, http debugging endpoints will be enabled on the given address. + +-interval :: + How often status updates are printed. Default is '5s'. + +-nobackup:: + Disable database backups. Not recommended. + +-parallel:: + Perform parallel conversions (up to GOMAXPROCS shards at once). + +-profile :: + Write a CPU profile to the path. + +-sz :: + Maximum size of individual TSM files. Defaults to 2147483648. + +-y:: + Don't ask, just convert. + +include::footer.txt[] diff -Nru influxdb-1.0.2+dfsg1/man/Makefile influxdb-1.1.1+dfsg1/man/Makefile --- influxdb-1.0.2+dfsg1/man/Makefile 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/man/Makefile 2016-12-06 21:36:15.000000000 +0000 @@ -10,6 +10,9 @@ MAN1_TXT += influxd-run.txt MAN1_TXT += influxd-version.txt MAN1_TXT += influx.txt +MAN1_TXT += influx_inspect.txt +MAN1_TXT += influx_stress.txt +MAN1_TXT += influx_tsm.txt MAN_TXT = $(MAN1_TXT) MAN_XML = $(patsubst %.txt,%.xml,$(MAN_TXT)) diff -Nru influxdb-1.0.2+dfsg1/man/README.md influxdb-1.1.1+dfsg1/man/README.md --- influxdb-1.0.2+dfsg1/man/README.md 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/man/README.md 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,38 @@ +# Building the Man Pages + +The man pages are created with `asciidoc`, `docbook`, and `xmlto`. + +## Debian/Ubuntu + +This is the easiest since Debian and Ubuntu automatically install the +dependencies correctly. + +```bash +$ sudo apt-get install -y build-essential asciidoc xmlto +``` + +You should then be able to run `make` and the man pages will be +produced. + +## Mac OS X + +Mac OS X also has the tools necessary to build the docs, but one of the +dependencies gets installed incorrectly and you need an environment +variable to run it correctly. + +Use Homebrew to install the dependencies. There might be other methods +to get the dependencies, but that's left up to the reader if they want +to use a different package manager. + +If you have Homebrew installed, you should already have the Xcode tools +and that should include `make`. + +```bash +$ brew install asciidoc xmlto +``` + +Then set the following environment variable everytime you run `make`. + +```bash +export XML_CATALOG_FILES=/usr/local/etc/xml/catalog +``` diff -Nru influxdb-1.0.2+dfsg1/models/inline_fnv.go influxdb-1.1.1+dfsg1/models/inline_fnv.go --- influxdb-1.0.2+dfsg1/models/inline_fnv.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/inline_fnv.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,27 @@ +package models // import "github.com/influxdata/influxdb/models" + +// from stdlib hash/fnv/fnv.go +const ( + prime64 = 1099511628211 + offset64 = 14695981039346656037 +) + +// InlineFNV64a is an alloc-free port of the standard library's fnv64a. +type InlineFNV64a uint64 + +func NewInlineFNV64a() InlineFNV64a { + return offset64 +} + +func (s *InlineFNV64a) Write(data []byte) (int, error) { + hash := uint64(*s) + for _, c := range data { + hash ^= uint64(c) + hash *= prime64 + } + *s = InlineFNV64a(hash) + return len(data), nil +} +func (s *InlineFNV64a) Sum64() uint64 { + return uint64(*s) +} diff -Nru influxdb-1.0.2+dfsg1/models/inline_fnv_test.go influxdb-1.1.1+dfsg1/models/inline_fnv_test.go --- influxdb-1.0.2+dfsg1/models/inline_fnv_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/inline_fnv_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,29 @@ +package models_test + +import ( + "hash/fnv" + "testing" + "testing/quick" + + "github.com/influxdata/influxdb/models" +) + +func TestInlineFNV64aEquivalenceFuzz(t *testing.T) { + f := func(data []byte) bool { + stdlibFNV := fnv.New64a() + stdlibFNV.Write(data) + want := stdlibFNV.Sum64() + + inlineFNV := models.NewInlineFNV64a() + inlineFNV.Write(data) + got := inlineFNV.Sum64() + + return want == got + } + cfg := &quick.Config{ + MaxCount: 10000, + } + if err := quick.Check(f, cfg); err != nil { + t.Fatal(err) + } +} diff -Nru influxdb-1.0.2+dfsg1/models/inline_strconv_parse.go influxdb-1.1.1+dfsg1/models/inline_strconv_parse.go --- influxdb-1.0.2+dfsg1/models/inline_strconv_parse.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/inline_strconv_parse.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,38 @@ +package models // import "github.com/influxdata/influxdb/models" + +import ( + "reflect" + "strconv" + "unsafe" +) + +// parseIntBytes is a zero-alloc wrapper around strconv.ParseInt. +func parseIntBytes(b []byte, base int, bitSize int) (i int64, err error) { + s := unsafeBytesToString(b) + return strconv.ParseInt(s, base, bitSize) +} + +// parseFloatBytes is a zero-alloc wrapper around strconv.ParseFloat. +func parseFloatBytes(b []byte, bitSize int) (float64, error) { + s := unsafeBytesToString(b) + return strconv.ParseFloat(s, bitSize) +} + +// parseBoolBytes is a zero-alloc wrapper around strconv.ParseBool. +func parseBoolBytes(b []byte) (bool, error) { + return strconv.ParseBool(unsafeBytesToString(b)) +} + +// unsafeBytesToString converts a []byte to a string without a heap allocation. +// +// It is unsafe, and is intended to prepare input to short-lived functions +// that require strings. +func unsafeBytesToString(in []byte) string { + src := *(*reflect.SliceHeader)(unsafe.Pointer(&in)) + dst := reflect.StringHeader{ + Data: src.Data, + Len: src.Len, + } + s := *(*string)(unsafe.Pointer(&dst)) + return s +} diff -Nru influxdb-1.0.2+dfsg1/models/inline_strconv_parse_test.go influxdb-1.1.1+dfsg1/models/inline_strconv_parse_test.go --- influxdb-1.0.2+dfsg1/models/inline_strconv_parse_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/inline_strconv_parse_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,103 @@ +package models + +import ( + "strconv" + "testing" + "testing/quick" +) + +func TestParseIntBytesEquivalenceFuzz(t *testing.T) { + f := func(b []byte, base int, bitSize int) bool { + exp, expErr := strconv.ParseInt(string(b), base, bitSize) + got, gotErr := parseIntBytes(b, base, bitSize) + + return exp == got && checkErrs(expErr, gotErr) + } + + cfg := &quick.Config{ + MaxCount: 10000, + } + + if err := quick.Check(f, cfg); err != nil { + t.Fatal(err) + } +} + +func TestParseIntBytesValid64bitBase10EquivalenceFuzz(t *testing.T) { + buf := []byte{} + f := func(n int64) bool { + buf = strconv.AppendInt(buf[:0], n, 10) + + exp, expErr := strconv.ParseInt(string(buf), 10, 64) + got, gotErr := parseIntBytes(buf, 10, 64) + + return exp == got && checkErrs(expErr, gotErr) + } + + cfg := &quick.Config{ + MaxCount: 10000, + } + + if err := quick.Check(f, cfg); err != nil { + t.Fatal(err) + } +} + +func TestParseFloatBytesEquivalenceFuzz(t *testing.T) { + f := func(b []byte, bitSize int) bool { + exp, expErr := strconv.ParseFloat(string(b), bitSize) + got, gotErr := parseFloatBytes(b, bitSize) + + return exp == got && checkErrs(expErr, gotErr) + } + + cfg := &quick.Config{ + MaxCount: 10000, + } + + if err := quick.Check(f, cfg); err != nil { + t.Fatal(err) + } +} + +func TestParseFloatBytesValid64bitEquivalenceFuzz(t *testing.T) { + buf := []byte{} + f := func(n float64) bool { + buf = strconv.AppendFloat(buf[:0], n, 'f', -1, 64) + + exp, expErr := strconv.ParseFloat(string(buf), 64) + got, gotErr := parseFloatBytes(buf, 64) + + return exp == got && checkErrs(expErr, gotErr) + } + + cfg := &quick.Config{ + MaxCount: 10000, + } + + if err := quick.Check(f, cfg); err != nil { + t.Fatal(err) + } +} + +func TestParseBoolBytesEquivalence(t *testing.T) { + var buf []byte + for _, s := range []string{"1", "t", "T", "TRUE", "true", "True", "0", "f", "F", "FALSE", "false", "False", "fail", "TrUe", "FAlSE", "numbers", ""} { + buf = append(buf[:0], s...) + + exp, expErr := strconv.ParseBool(s) + got, gotErr := parseBoolBytes(buf) + + if got != exp || !checkErrs(expErr, gotErr) { + t.Errorf("Failed to parse boolean value %q correctly: wanted (%t, %v), got (%t, %v)", s, exp, expErr, got, gotErr) + } + } +} + +func checkErrs(a, b error) bool { + if (a == nil) != (b == nil) { + return false + } + + return a == nil || a.Error() == b.Error() +} diff -Nru influxdb-1.0.2+dfsg1/models/points.go influxdb-1.1.1+dfsg1/models/points.go --- influxdb-1.0.2+dfsg1/models/points.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/points.go 2016-12-06 21:36:15.000000000 +0000 @@ -5,7 +5,6 @@ "encoding/binary" "errors" "fmt" - "hash/fnv" "math" "sort" "strconv" @@ -75,6 +74,48 @@ // is a timestamp associated with the point, then it will be rounded to the // given duration RoundedString(d time.Duration) string + + // Split will attempt to return multiple points with the same timestamp whose + // string representations are no longer than size. Points with a single field or + // a point without a timestamp may exceed the requested size. + Split(size int) []Point + + // Round will round the timestamp of the point to the given duration + Round(d time.Duration) + + // StringSize returns the length of the string that would be returned by String() + StringSize() int + + // AppendString appends the result of String() to the provided buffer and returns + // the result, potentially reducing string allocations + AppendString(buf []byte) []byte + + // FieldIterator retuns a FieldIterator that can be used to traverse the + // fields of a point without constructing the in-memory map + FieldIterator() FieldIterator +} + +type FieldType int + +const ( + Integer FieldType = iota + Float + Boolean + String + Empty +) + +type FieldIterator interface { + Next() bool + FieldKey() []byte + Type() FieldType + StringValue() string + IntegerValue() int64 + BooleanValue() bool + FloatValue() float64 + + Delete() + Reset() } // Points represents a sortable list of points by timestamp. @@ -107,6 +148,11 @@ // cached version of parsed name from key cachedName string + + // cached version of parsed tags + cachedTags Tags + + it fieldIterator } const ( @@ -139,14 +185,14 @@ } // ParseKey returns the measurement name and tags from a point. -func ParseKey(buf string) (string, Tags, error) { +func ParseKey(buf []byte) (string, Tags, error) { // Ignore the error because scanMeasurement returns "missing fields" which we ignore // when just parsing a key - state, i, _ := scanMeasurement([]byte(buf), 0) + state, i, _ := scanMeasurement(buf, 0) var tags Tags if state == tagKeyState { - tags = parseTags([]byte(buf)) + tags = parseTags(buf) // scanMeasurement returns the location of the comma if there are tags, strip that off return string(buf[:i-1]), tags, nil } @@ -156,7 +202,7 @@ // ParsePointsWithPrecision is similar to ParsePoints, but allows the // caller to provide a precision for time. func ParsePointsWithPrecision(buf []byte, defaultTime time.Time, precision string) ([]Point, error) { - points := []Point{} + points := make([]Point, 0, bytes.Count(buf, []byte{'\n'})+1) var ( pos int block []byte @@ -187,7 +233,7 @@ block = block[:len(block)-1] } - pt, err := parsePoint(block[start:len(block)], defaultTime, precision) + pt, err := parsePoint(block[start:], defaultTime, precision) if err != nil { failed = append(failed, fmt.Sprintf("unable to parse '%s': %v", string(block[start:len(block)]), err)) } else { @@ -245,7 +291,7 @@ pt.time = defaultTime pt.SetPrecision(precision) } else { - ts, err := strconv.ParseInt(string(ts), 10, 64) + ts, err := parseIntBytes(ts, 10, 64) if err != nil { return nil, err } @@ -782,14 +828,14 @@ // Parse the int to check bounds the number of digits could be larger than the max range // We subtract 1 from the index to remove the `i` from our tests if len(buf[start:i-1]) >= maxInt64Digits || len(buf[start:i-1]) >= minInt64Digits { - if _, err := strconv.ParseInt(string(buf[start:i-1]), 10, 64); err != nil { + if _, err := parseIntBytes(buf[start:i-1], 10, 64); err != nil { return i, fmt.Errorf("unable to parse integer %s: %s", buf[start:i-1], err) } } } else { // Parse the float to check bounds if it's scientific or the number of digits could be larger than the max range if scientific || len(buf[start:i]) >= maxFloat64Digits || len(buf[start:i]) >= minFloat64Digits { - if _, err := strconv.ParseFloat(string(buf[start:i]), 10); err != nil { + if _, err := parseFloatBytes(buf[start:i], 10); err != nil { return i, fmt.Errorf("invalid float") } } @@ -991,13 +1037,9 @@ func scanFieldValue(buf []byte, i int) (int, []byte) { start := i quoted := false - for { - if i >= len(buf) { - break - } - - // Only escape char for a field value is a double-quote - if buf[i] == '\\' && i+1 < len(buf) && buf[i+1] == '"' { + for i < len(buf) { + // Only escape char for a field value is a double-quote and backslash + if buf[i] == '\\' && i+1 < len(buf) && (buf[i+1] == '"' || buf[i+1] == '\\') { i += 2 continue } @@ -1117,20 +1159,42 @@ // NewPoint returns a new point with the given measurement name, tags, fields and timestamp. If // an unsupported field value (NaN) or out of range time is passed, this function returns an error. -func NewPoint(name string, tags Tags, fields Fields, time time.Time) (Point, error) { +func NewPoint(name string, tags Tags, fields Fields, t time.Time) (Point, error) { + key, err := pointKey(name, tags, fields, t) + if err != nil { + return nil, err + } + + return &point{ + key: key, + time: t, + fields: fields.MarshalBinary(), + }, nil +} + +// pointKey checks some basic requirements for valid points, and returns the +// key, along with an possible error +func pointKey(measurement string, tags Tags, fields Fields, t time.Time) ([]byte, error) { if len(fields) == 0 { return nil, ErrPointMustHaveAField } - if !time.IsZero() { - if err := CheckTime(time); err != nil { + + if !t.IsZero() { + if err := CheckTime(t); err != nil { return nil, err } } for key, value := range fields { - if fv, ok := value.(float64); ok { + switch value := value.(type) { + case float64: + // Ensure the caller validates and handles invalid field values + if math.IsNaN(value) { + return nil, fmt.Errorf("NaN is an unsupported value for field %s", key) + } + case float32: // Ensure the caller validates and handles invalid field values - if math.IsNaN(fv) { + if math.IsNaN(float64(value)) { return nil, fmt.Errorf("NaN is an unsupported value for field %s", key) } } @@ -1139,16 +1203,12 @@ } } - key := MakeKey([]byte(name), tags) + key := MakeKey([]byte(measurement), tags) if len(key) > MaxKeyLength { return nil, fmt.Errorf("max key length exceeded: %v > %v", len(key), MaxKeyLength) } - return &point{ - key: key, - time: time, - fields: fields.MarshalBinary(), - }, nil + return key, nil } // NewPointFromBytes returns a new Point from a marshalled Point. @@ -1215,45 +1275,57 @@ p.time = t } +// Round implements Point.Round +func (p *point) Round(d time.Duration) { + p.time = p.time.Round(d) +} + // Tags returns the tag set for the point func (p *point) Tags() Tags { - return parseTags(p.key) + if p.cachedTags != nil { + return p.cachedTags + } + p.cachedTags = parseTags(p.key) + return p.cachedTags } func parseTags(buf []byte) Tags { - tags := make(map[string]string, bytes.Count(buf, []byte(","))) - hasEscape := bytes.IndexByte(buf, '\\') != -1 + if len(buf) == 0 { + return nil + } - if len(buf) != 0 { - pos, name := scanTo(buf, 0, ',') + pos, name := scanTo(buf, 0, ',') - // it's an empyt key, so there are no tags - if len(name) == 0 { - return tags - } + // it's an empty key, so there are no tags + if len(name) == 0 { + return nil + } - i := pos + 1 - var key, value []byte - for { - if i >= len(buf) { - break - } - i, key = scanTo(buf, i, '=') - i, value = scanTagValue(buf, i+1) + tags := make(Tags, 0, bytes.Count(buf, []byte(","))) + hasEscape := bytes.IndexByte(buf, '\\') != -1 - if len(value) == 0 { - continue - } + i := pos + 1 + var key, value []byte + for { + if i >= len(buf) { + break + } + i, key = scanTo(buf, i, '=') + i, value = scanTagValue(buf, i+1) - if hasEscape { - tags[string(unescapeTag(key))] = string(unescapeTag(value)) - } else { - tags[string(key)] = string(value) - } + if len(value) == 0 { + continue + } - i++ + if hasEscape { + tags = append(tags, Tag{Key: unescapeTag(key), Value: unescapeTag(value)}) + } else { + tags = append(tags, Tag{Key: key, Value: value}) } + + i++ } + return tags } @@ -1267,12 +1339,15 @@ // SetTags replaces the tags for the point func (p *point) SetTags(tags Tags) { p.key = MakeKey([]byte(p.Name()), tags) + p.cachedTags = tags } // AddTag adds or replaces a tag value for a point func (p *point) AddTag(key, value string) { tags := p.Tags() - tags[key] = value + tags = append(tags, Tag{Key: []byte(key), Value: []byte(value)}) + sort.Sort(tags) + p.cachedTags = tags p.key = MakeKey([]byte(p.Name()), tags) } @@ -1309,6 +1384,41 @@ return string(p.Key()) + " " + string(p.fields) + " " + strconv.FormatInt(p.UnixNano(), 10) } +// AppendString implements Point.AppendString +func (p *point) AppendString(buf []byte) []byte { + buf = append(buf, p.key...) + buf = append(buf, ' ') + buf = append(buf, p.fields...) + + if !p.time.IsZero() { + buf = append(buf, ' ') + buf = strconv.AppendInt(buf, p.UnixNano(), 10) + } + + return buf +} + +func (p *point) StringSize() int { + size := len(p.key) + len(p.fields) + 1 + + if !p.time.IsZero() { + digits := 1 // even "0" has one digit + t := p.UnixNano() + if t < 0 { + // account for negative sign, then negate + digits++ + t = -t + } + for t > 9 { // already accounted for one digit + digits++ + t /= 10 + } + size += digits + 1 // digits and a space + } + + return size +} + func (p *point) MarshalBinary() ([]byte, error) { tb, err := p.time.MarshalBinary() if err != nil { @@ -1368,11 +1478,28 @@ } func (p *point) unmarshalBinary() Fields { - return newFieldsFromBinary(p.fields) + iter := p.FieldIterator() + fields := make(Fields, 8) + for iter.Next() { + if len(iter.FieldKey()) == 0 { + continue + } + switch iter.Type() { + case Float: + fields[string(iter.FieldKey())] = iter.FloatValue() + case Integer: + fields[string(iter.FieldKey())] = iter.IntegerValue() + case String: + fields[string(iter.FieldKey())] = iter.StringValue() + case Boolean: + fields[string(iter.FieldKey())] = iter.BooleanValue() + } + } + return fields } func (p *point) HashID() uint64 { - h := fnv.New64a() + h := NewInlineFNV64a() h.Write(p.key) sum := h.Sum64() return sum @@ -1382,64 +1509,176 @@ return p.Time().UnixNano() } -// Tags represents a mapping between a Point's tag names and their -// values. -type Tags map[string]string +func (p *point) Split(size int) []Point { + if p.time.IsZero() || len(p.String()) <= size { + return []Point{p} + } + + // key string, timestamp string, spaces + size -= len(p.key) + len(strconv.FormatInt(p.time.UnixNano(), 10)) + 2 + + var points []Point + var start, cur int + + for cur < len(p.fields) { + end, _ := scanTo(p.fields, cur, '=') + end, _ = scanFieldValue(p.fields, end+1) + + if cur > start && end-start > size { + points = append(points, &point{ + key: p.key, + time: p.time, + fields: p.fields[start : cur-1], + }) + start = cur + } + + cur = end + 1 + } + + points = append(points, &point{ + key: p.key, + time: p.time, + fields: p.fields[start:], + }) + + return points +} + +// Tag represents a single key/value tag pair. +type Tag struct { + Key []byte + Value []byte +} + +// Tags represents a sorted list of tags. +type Tags []Tag + +// NewTags returns a new Tags from a map. +func NewTags(m map[string]string) Tags { + if len(m) == 0 { + return nil + } + a := make(Tags, 0, len(m)) + for k, v := range m { + a = append(a, Tag{Key: []byte(k), Value: []byte(v)}) + } + sort.Sort(a) + return a +} + +func (a Tags) Len() int { return len(a) } +func (a Tags) Less(i, j int) bool { return bytes.Compare(a[i].Key, a[j].Key) == -1 } +func (a Tags) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// Get returns the value for a key. +func (a Tags) Get(key []byte) []byte { + // OPTIMIZE: Use sort.Search if tagset is large. + + for _, t := range a { + if bytes.Equal(t.Key, key) { + return t.Value + } + } + return nil +} + +// GetString returns the string value for a string key. +func (a Tags) GetString(key string) string { + return string(a.Get([]byte(key))) +} + +// Set sets the value for a key. +func (a *Tags) Set(key, value []byte) { + for _, t := range *a { + if bytes.Equal(t.Key, key) { + t.Value = value + return + } + } + *a = append(*a, Tag{Key: key, Value: value}) + sort.Sort(*a) +} + +// SetString sets the string value for a string key. +func (a *Tags) SetString(key, value string) { + a.Set([]byte(key), []byte(value)) +} + +// Delete removes a tag by key. +func (a *Tags) Delete(key []byte) { + for i, t := range *a { + if bytes.Equal(t.Key, key) { + copy((*a)[i:], (*a)[i+1:]) + (*a)[len(*a)-1] = Tag{} + *a = (*a)[:len(*a)-1] + return + } + } +} + +// Map returns a map representation of the tags. +func (a Tags) Map() map[string]string { + m := make(map[string]string, len(a)) + for _, t := range a { + m[string(t.Key)] = string(t.Value) + } + return m +} // Merge merges the tags combining the two. If both define a tag with the // same key, the merged value overwrites the old value. // A new map is returned. -func (t Tags) Merge(other map[string]string) Tags { - merged := make(map[string]string, len(t)+len(other)) - for k, v := range t { - merged[k] = v +func (a Tags) Merge(other map[string]string) Tags { + merged := make(map[string]string, len(a)+len(other)) + for _, t := range a { + merged[string(t.Key)] = string(t.Value) } for k, v := range other { merged[k] = v } - return Tags(merged) + return NewTags(merged) } // HashKey hashes all of a tag's keys. -func (t Tags) HashKey() []byte { +func (a Tags) HashKey() []byte { // Empty maps marshal to empty bytes. - if len(t) == 0 { + if len(a) == 0 { return nil } - escaped := Tags{} - for k, v := range t { - ek := escapeTag([]byte(k)) - ev := escapeTag([]byte(v)) + escaped := make(Tags, 0, len(a)) + for _, t := range a { + ek := escapeTag(t.Key) + ev := escapeTag(t.Value) if len(ev) > 0 { - escaped[string(ek)] = string(ev) + escaped = append(escaped, Tag{Key: ek, Value: ev}) } } // Extract keys and determine final size. sz := len(escaped) + (len(escaped) * 2) // separators - keys := make([]string, len(escaped)+1) - i := 0 - for k, v := range escaped { - keys[i] = k - i++ - sz += len(k) + len(v) + keys := make([][]byte, len(escaped)+1) + for i, t := range escaped { + keys[i] = t.Key + sz += len(t.Key) + len(t.Value) } - keys = keys[:i] - sort.Strings(keys) + keys = keys[:len(escaped)] + sort.Sort(byteSlices(keys)) + // Generate marshaled bytes. b := make([]byte, sz) buf := b idx := 0 - for _, k := range keys { + for i, k := range keys { buf[idx] = ',' idx++ copy(buf[idx:idx+len(k)], k) idx += len(k) buf[idx] = '=' idx++ - v := escaped[k] + v := escaped[i].Value copy(buf[idx:idx+len(v)], v) idx += len(v) } @@ -1453,140 +1692,225 @@ func parseNumber(val []byte) (interface{}, error) { if val[len(val)-1] == 'i' { val = val[:len(val)-1] - return strconv.ParseInt(string(val), 10, 64) + return parseIntBytes(val, 10, 64) } for i := 0; i < len(val); i++ { // If there is a decimal or an N (NaN), I (Inf), parse as float if val[i] == '.' || val[i] == 'N' || val[i] == 'n' || val[i] == 'I' || val[i] == 'i' || val[i] == 'e' { - return strconv.ParseFloat(string(val), 64) + return parseFloatBytes(val, 64) } if val[i] < '0' && val[i] > '9' { return string(val), nil } } - return strconv.ParseFloat(string(val), 64) + return parseFloatBytes(val, 64) } -func newFieldsFromBinary(buf []byte) Fields { - fields := make(Fields, 8) - var ( - i int - name, valueBuf []byte - value interface{} - err error - ) - for i < len(buf) { +func (p *point) FieldIterator() FieldIterator { + p.Reset() + return p +} - i, name = scanTo(buf, i, '=') - name = escape.Unescape(name) +type fieldIterator struct { + start, end int + key, keybuf []byte + valueBuf []byte + fieldType FieldType +} - i, valueBuf = scanFieldValue(buf, i+1) - if len(name) > 0 { - if len(valueBuf) == 0 { - fields[string(name)] = nil - continue - } +func (p *point) Next() bool { + p.it.start = p.it.end + if p.it.start >= len(p.fields) { + return false + } - // If the first char is a double-quote, then unmarshal as string - if valueBuf[0] == '"' { - value = unescapeStringField(string(valueBuf[1 : len(valueBuf)-1])) - // Check for numeric characters and special NaN or Inf - } else if (valueBuf[0] >= '0' && valueBuf[0] <= '9') || valueBuf[0] == '-' || valueBuf[0] == '.' || - valueBuf[0] == 'N' || valueBuf[0] == 'n' || // NaN - valueBuf[0] == 'I' || valueBuf[0] == 'i' { // Inf + p.it.end, p.it.key = scanTo(p.fields, p.it.start, '=') + if escape.IsEscaped(p.it.key) { + p.it.keybuf = escape.AppendUnescaped(p.it.keybuf[:0], p.it.key) + p.it.key = p.it.keybuf + } - value, err = parseNumber(valueBuf) - if err != nil { - panic(fmt.Sprintf("unable to parse number value '%v': %v", string(valueBuf), err)) - } + p.it.end, p.it.valueBuf = scanFieldValue(p.fields, p.it.end+1) + p.it.end++ - // Otherwise parse it as bool - } else { - value, err = strconv.ParseBool(string(valueBuf)) - if err != nil { - panic(fmt.Sprintf("unable to parse bool value '%v': %v\n", string(valueBuf), err)) - } - } - fields[string(name)] = value + if len(p.it.valueBuf) == 0 { + p.it.fieldType = Empty + return true + } + + c := p.it.valueBuf[0] + + if c == '"' { + p.it.fieldType = String + return true + } + + if strings.IndexByte(`0123456789-.nNiI`, c) >= 0 { + if p.it.valueBuf[len(p.it.valueBuf)-1] == 'i' { + p.it.fieldType = Integer + p.it.valueBuf = p.it.valueBuf[:len(p.it.valueBuf)-1] + } else { + p.it.fieldType = Float } - i++ + return true } - return fields + + // to keep the same behavior that currently exists, default to boolean + p.it.fieldType = Boolean + return true +} + +func (p *point) FieldKey() []byte { + return p.it.key +} + +func (p *point) Type() FieldType { + return p.it.fieldType +} + +func (p *point) StringValue() string { + return unescapeStringField(string(p.it.valueBuf[1 : len(p.it.valueBuf)-1])) +} + +func (p *point) IntegerValue() int64 { + n, err := parseIntBytes(p.it.valueBuf, 10, 64) + if err != nil { + panic(fmt.Sprintf("unable to parse integer value %q: %v", p.it.valueBuf, err)) + } + return n +} + +func (p *point) BooleanValue() bool { + b, err := parseBoolBytes(p.it.valueBuf) + if err != nil { + panic(fmt.Sprintf("unable to parse bool value %q: %v", p.it.valueBuf, err)) + } + return b +} + +func (p *point) FloatValue() float64 { + f, err := parseFloatBytes(p.it.valueBuf, 64) + if err != nil { + // panic because that's what the non-iterator code does + panic(fmt.Sprintf("unable to parse floating point value %q: %v", p.it.valueBuf, err)) + } + return f +} + +func (p *point) Delete() { + switch { + case p.it.end == p.it.start: + case p.it.end >= len(p.fields): + p.fields = p.fields[:p.it.start] + case p.it.start == 0: + p.fields = p.fields[p.it.end:] + default: + p.fields = append(p.fields[:p.it.start], p.fields[p.it.end:]...) + } + + p.it.end = p.it.start + p.it.key = nil + p.it.valueBuf = nil + p.it.fieldType = Empty +} + +func (p *point) Reset() { + p.it.fieldType = Empty + p.it.key = nil + p.it.valueBuf = nil + p.it.start = 0 + p.it.end = 0 } // MarshalBinary encodes all the fields to their proper type and returns the binary // represenation // NOTE: uint64 is specifically not supported due to potential overflow when we decode // again later to an int64 +// NOTE2: uint is accepted, and may be 64 bits, and is for some reason accepted... func (p Fields) MarshalBinary() []byte { - b := []byte{} - keys := make([]string, len(p)) - i := 0 + var b []byte + keys := make([]string, 0, len(p)) + for k := range p { - keys[i] = k - i++ + keys = append(keys, k) } - sort.Strings(keys) - for _, k := range keys { - v := p[k] - b = append(b, []byte(escape.String(k))...) - b = append(b, '=') - switch t := v.(type) { - case int: - b = append(b, []byte(strconv.FormatInt(int64(t), 10))...) - b = append(b, 'i') - case int8: - b = append(b, []byte(strconv.FormatInt(int64(t), 10))...) - b = append(b, 'i') - case int16: - b = append(b, []byte(strconv.FormatInt(int64(t), 10))...) - b = append(b, 'i') - case int32: - b = append(b, []byte(strconv.FormatInt(int64(t), 10))...) - b = append(b, 'i') - case int64: - b = append(b, []byte(strconv.FormatInt(t, 10))...) - b = append(b, 'i') - case uint: - b = append(b, []byte(strconv.FormatInt(int64(t), 10))...) - b = append(b, 'i') - case uint8: - b = append(b, []byte(strconv.FormatInt(int64(t), 10))...) - b = append(b, 'i') - case uint16: - b = append(b, []byte(strconv.FormatInt(int64(t), 10))...) - b = append(b, 'i') - case uint32: - b = append(b, []byte(strconv.FormatInt(int64(t), 10))...) - b = append(b, 'i') - case float32: - val := []byte(strconv.FormatFloat(float64(t), 'f', -1, 32)) - b = append(b, val...) - case float64: - val := []byte(strconv.FormatFloat(t, 'f', -1, 64)) - b = append(b, val...) - case bool: - b = append(b, []byte(strconv.FormatBool(t))...) - case []byte: - b = append(b, t...) - case string: - b = append(b, '"') - b = append(b, []byte(EscapeStringField(t))...) - b = append(b, '"') - case nil: - // skip - default: - // Can't determine the type, so convert to string - b = append(b, '"') - b = append(b, []byte(EscapeStringField(fmt.Sprintf("%v", v)))...) - b = append(b, '"') + // Not really necessary, can probably be removed. + sort.Strings(keys) + for i, k := range keys { + if i > 0 { + b = append(b, ',') } - b = append(b, ',') + b = appendField(b, k, p[k]) } - if len(b) > 0 { - return b[0 : len(b)-1] + + return b +} + +func appendField(b []byte, k string, v interface{}) []byte { + b = append(b, []byte(escape.String(k))...) + b = append(b, '=') + + // check popular types first + switch v := v.(type) { + case float64: + b = strconv.AppendFloat(b, v, 'f', -1, 64) + case int64: + b = strconv.AppendInt(b, v, 10) + b = append(b, 'i') + case string: + b = append(b, '"') + b = append(b, []byte(EscapeStringField(v))...) + b = append(b, '"') + case bool: + b = strconv.AppendBool(b, v) + case int32: + b = strconv.AppendInt(b, int64(v), 10) + b = append(b, 'i') + case int16: + b = strconv.AppendInt(b, int64(v), 10) + b = append(b, 'i') + case int8: + b = strconv.AppendInt(b, int64(v), 10) + b = append(b, 'i') + case int: + b = strconv.AppendInt(b, int64(v), 10) + b = append(b, 'i') + case uint32: + b = strconv.AppendInt(b, int64(v), 10) + b = append(b, 'i') + case uint16: + b = strconv.AppendInt(b, int64(v), 10) + b = append(b, 'i') + case uint8: + b = strconv.AppendInt(b, int64(v), 10) + b = append(b, 'i') + // TODO: 'uint' should be considered just as "dangerous" as a uint64, + // perhaps the value should be checked and capped at MaxInt64? We could + // then include uint64 as an accepted value + case uint: + b = strconv.AppendInt(b, int64(v), 10) + b = append(b, 'i') + case float32: + b = strconv.AppendFloat(b, float64(v), 'f', -1, 32) + case []byte: + b = append(b, v...) + case nil: + // skip + default: + // Can't determine the type, so convert to string + b = append(b, '"') + b = append(b, []byte(EscapeStringField(fmt.Sprintf("%v", v)))...) + b = append(b, '"') + } + return b } + +type byteSlices [][]byte + +func (a byteSlices) Len() int { return len(a) } +func (a byteSlices) Less(i, j int) bool { return bytes.Compare(a[i], a[j]) == -1 } +func (a byteSlices) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff -Nru influxdb-1.0.2+dfsg1/models/points_test.go influxdb-1.1.1+dfsg1/models/points_test.go --- influxdb-1.0.2+dfsg1/models/points_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/points_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -15,7 +15,15 @@ ) var ( - tags = models.Tags{"foo": "bar", "apple": "orange", "host": "serverA", "region": "uswest"} + tags = models.NewTags(map[string]string{"foo": "bar", "apple": "orange", "host": "serverA", "region": "uswest"}) + fields = models.Fields{ + "int64": int64(math.MaxInt64), + "uint32": uint32(math.MaxUint32), + "string": "String field that has a decent length, probably some log message or something", + "boolean": false, + "float64-tiny": float64(math.SmallestNonzeroFloat64), + "float64-large": float64(math.MaxFloat64), + } maxFloat64 = strconv.FormatFloat(math.MaxFloat64, 'f', 1, 64) minFloat64 = strconv.FormatFloat(-math.MaxFloat64, 'f', 1, 64) ) @@ -35,6 +43,72 @@ } } +func TestPoint_StringSize(t *testing.T) { + testPoint_cube(t, func(p models.Point) { + l := p.StringSize() + s := p.String() + + if l != len(s) { + t.Errorf("Incorrect length for %q. got %v, exp %v", s, l, len(s)) + } + }) + +} + +func TestPoint_AppendString(t *testing.T) { + testPoint_cube(t, func(p models.Point) { + got := p.AppendString(nil) + exp := []byte(p.String()) + + if !reflect.DeepEqual(exp, got) { + t.Errorf("AppendString() didn't match String(): got %v, exp %v", got, exp) + } + }) +} + +func testPoint_cube(t *testing.T, f func(p models.Point)) { + // heard of a table-driven test? let's make a cube-driven test... + tagList := []models.Tags{nil, {models.Tag{Key: []byte("foo"), Value: []byte("bar")}}, tags} + fieldList := []models.Fields{{"a": 42.0}, {"a": 42, "b": "things"}, fields} + timeList := []time.Time{time.Time{}, time.Unix(0, 0), time.Unix(-34526, 0), time.Unix(231845, 0), time.Now()} + + for _, tagSet := range tagList { + for _, fieldSet := range fieldList { + for _, pointTime := range timeList { + p, err := models.NewPoint("test", tagSet, fieldSet, pointTime) + if err != nil { + t.Errorf("unexpected error creating point: %v", err) + continue + } + + f(p) + } + } + } +} + +var p models.Point + +func BenchmarkNewPoint(b *testing.B) { + ts := time.Now() + for i := 0; i < b.N; i++ { + p, _ = models.NewPoint("measurement", tags, fields, ts) + } +} + +func BenchmarkParsePointNoTags5000(b *testing.B) { + var batch [5000]string + for i := 0; i < len(batch); i++ { + batch[i] = `cpu value=1i 1000000000` + } + lines := strings.Join(batch[:], "\n") + b.ResetTimer() + for i := 0; i < b.N; i++ { + models.ParsePoints([]byte(lines)) + b.SetBytes(int64(len(lines))) + } +} + func BenchmarkParsePointNoTags(b *testing.B) { line := `cpu value=1i 1000000000` for i := 0; i < b.N; i++ { @@ -115,7 +189,7 @@ func BenchmarkParseKey(b *testing.B) { line := `cpu,region=us-west,host=serverA,env=prod,target=servers,zone=1c,tag1=value1,tag2=value2,tag3=value3,tag4=value4,tag5=value5` for i := 0; i < b.N; i++ { - models.ParseKey(line) + models.ParseKey([]byte(line)) } } @@ -163,9 +237,9 @@ t.Errorf(`ParsePoints("%s") tags mismatch. got %v, exp %v`, line, pts[0].Tags(), exp) } - for tag, value := range pts[0].Tags() { - if value != point.RawTags[tag] { - t.Errorf(`ParsePoints("%s") tags mismatch. got %v, exp %v`, line, value, point.RawTags[tag]) + for _, tag := range pts[0].Tags() { + if !bytes.Equal(tag.Value, point.RawTags.Get(tag.Key)) { + t.Errorf(`ParsePoints("%s") tags mismatch. got %s, exp %s`, line, tag.Value, point.RawTags.Get(tag.Key)) } } @@ -639,7 +713,7 @@ test(t, `foo\,bar value=1i`, NewTestPoint( "foo,bar", // comma in the name - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": int64(1), }, @@ -649,9 +723,9 @@ test(t, `cpu\,main,regions=east value=1.0`, NewTestPoint( "cpu,main", // comma in the name - models.Tags{ + models.NewTags(map[string]string{ "regions": "east", - }, + }), models.Fields{ "value": 1.0, }, @@ -661,9 +735,9 @@ test(t, `cpu\ load,region=east value=1.0`, NewTestPoint( "cpu load", // space in the name - models.Tags{ + models.NewTags(map[string]string{ "region": "east", - }, + }), models.Fields{ "value": 1.0, }, @@ -673,9 +747,9 @@ test(t, `cpu\=load,region=east value=1.0`, NewTestPoint( `cpu\=load`, // backslash is literal - models.Tags{ + models.NewTags(map[string]string{ "region": "east", - }, + }), models.Fields{ "value": 1.0, }, @@ -685,9 +759,9 @@ test(t, `cpu=load,region=east value=1.0`, NewTestPoint( `cpu=load`, // literal equals is fine in measurement name - models.Tags{ + models.NewTags(map[string]string{ "region": "east", - }, + }), models.Fields{ "value": 1.0, }, @@ -696,9 +770,9 @@ // commas in tag names test(t, `cpu,region\,zone=east value=1.0`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "region,zone": "east", // comma in the tag key - }, + }), models.Fields{ "value": 1.0, }, @@ -707,9 +781,9 @@ // spaces in tag name test(t, `cpu,region\ zone=east value=1.0`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "region zone": "east", // space in the tag name - }, + }), models.Fields{ "value": 1.0, }, @@ -718,9 +792,9 @@ // backslash with escaped equals in tag name test(t, `cpu,reg\\=ion=east value=1.0`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ `reg\=ion`: "east", - }, + }), models.Fields{ "value": 1.0, }, @@ -729,9 +803,9 @@ // space is tag name test(t, `cpu,\ =east value=1.0`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ " ": "east", // tag name is single space - }, + }), models.Fields{ "value": 1.0, }, @@ -740,9 +814,9 @@ // commas in tag values test(t, `cpu,regions=east\,west value=1.0`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": "east,west", // comma in the tag value - }, + }), models.Fields{ "value": 1.0, }, @@ -752,9 +826,9 @@ test(t, `cpu,regions=\\ east value=1.0`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": `\ east`, - }, + }), models.Fields{ "value": 1.0, }, @@ -764,9 +838,9 @@ test(t, `cpu,regions=eas\\ t value=1.0`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": `eas\ t`, - }, + }), models.Fields{ "value": 1.0, }, @@ -776,9 +850,9 @@ test(t, `cpu,regions=east\\ value=1.0`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": `east\ `, - }, + }), models.Fields{ "value": 1.0, }, @@ -787,9 +861,9 @@ // spaces in tag values test(t, `cpu,regions=east\ west value=1.0`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": "east west", // comma in the tag value - }, + }), models.Fields{ "value": 1.0, }, @@ -798,9 +872,9 @@ // commas in field keys test(t, `cpu,regions=east value\,ms=1.0`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": "east", - }, + }), models.Fields{ "value,ms": 1.0, // comma in the field keys }, @@ -809,9 +883,9 @@ // spaces in field keys test(t, `cpu,regions=east value\ ms=1.0`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": "east", - }, + }), models.Fields{ "value ms": 1.0, // comma in the field keys }, @@ -820,10 +894,10 @@ // tag with no value test(t, `cpu,regions=east value="1"`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": "east", "foobar": "", - }, + }), models.Fields{ "value": "1", }, @@ -832,9 +906,9 @@ // commas in field values test(t, `cpu,regions=east value="1,0"`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": "east", - }, + }), models.Fields{ "value": "1,0", // comma in the field value }, @@ -844,9 +918,9 @@ test(t, `cpu,regions=eas\t value=1.0`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": "eas\\t", - }, + }), models.Fields{ "value": 1.0, }, @@ -856,9 +930,9 @@ test(t, `cpu,regions=\\,\,\=east value=1.0`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "regions": `\,,=east`, - }, + }), models.Fields{ "value": 1.0, }, @@ -868,7 +942,7 @@ test(t, `cpu \a=1i`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "\\a": int64(1), // Left as parsed since it's not a known escape sequence. }, @@ -878,9 +952,9 @@ test(t, `cpu=load,equals\=foo=tag\=value value=1i`, NewTestPoint( "cpu=load", // Not escaped - models.Tags{ + models.NewTags(map[string]string{ "equals=foo": "tag=value", // Tag and value unescaped - }, + }), models.Fields{ "value": int64(1), }, @@ -892,7 +966,7 @@ test(t, "cpu,host=serverA,region=us-east value=1.0 1000000000", NewTestPoint("cpu", - models.Tags{"host": "serverA", "region": "us-east"}, + models.NewTags(map[string]string{"host": "serverA", "region": "us-east"}), models.Fields{"value": 1.0}, time.Unix(1, 0))) } @@ -924,10 +998,10 @@ func TestParsePointWithStringField(t *testing.T) { test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo",str2="bar" 1000000000`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": 1.0, "str": "foo", @@ -938,10 +1012,10 @@ test(t, `cpu,host=serverA,region=us-east str="foo \" bar" 1000000000`, NewTestPoint("cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "str": `foo " bar`, }, @@ -954,10 +1028,10 @@ test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo bar" 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": 1.0, "str": "foo bar", // spaces in string value @@ -970,10 +1044,10 @@ test(t, "cpu,host=serverA,region=us-east value=1.0,str=\"foo\nbar\" 1000000000", NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": 1.0, "str": "foo\nbar", // newline in string value @@ -987,10 +1061,10 @@ test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo\,bar" 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": 1.0, "str": `foo\,bar`, // commas in string value @@ -1002,16 +1076,31 @@ test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo,bar" 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": 1.0, "str": "foo,bar", // commas in string value }, time.Unix(1, 0)), ) + + // string w/ trailing escape chars + test(t, `cpu,host=serverA,region=us-east str="foo\\",str2="bar" 1000000000`, + NewTestPoint( + "cpu", + models.NewTags(map[string]string{ + "host": "serverA", + "region": "us-east", + }), + models.Fields{ + "str": "foo\\", // trailing escape char + "str2": "bar", + }, + time.Unix(1, 0)), + ) } func TestParsePointQuotedMeasurement(t *testing.T) { @@ -1019,10 +1108,10 @@ test(t, `"cpu",host=serverA,region=us-east value=1.0 1000000000`, NewTestPoint( `"cpu"`, - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": 1.0, }, @@ -1034,10 +1123,10 @@ test(t, `cpu,"host"="serverA",region=us-east value=1.0 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ `"host"`: `"serverA"`, "region": "us-east", - }, + }), models.Fields{ "value": 1.0, }, @@ -1056,7 +1145,7 @@ } // Expected " in the tag value - exp := models.MustNewPoint("baz", models.Tags{"mytag": `"a`}, + exp := models.MustNewPoint("baz", models.NewTags(map[string]string{"mytag": `"a`}), models.Fields{"x": float64(1)}, time.Unix(0, 1441103862125)) if pts[0].String() != exp.String() { @@ -1064,7 +1153,7 @@ } // Expected two points to ensure we did not overscan the line - exp = models.MustNewPoint("baz", models.Tags{"mytag": `a`}, + exp = models.MustNewPoint("baz", models.NewTags(map[string]string{"mytag": `a`}), models.Fields{"z": float64(1)}, time.Unix(0, 1441103862126)) if pts[1].String() != exp.String() { @@ -1078,10 +1167,10 @@ test(t, `cpu,host=serverA,region=us-east value="{Hello\"{,}\" World}" 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": `{Hello"{,}" World}`, }, @@ -1092,10 +1181,10 @@ test(t, `cpu,host=serverA,region=us-east value="{Hello\"{\,}\" World}" 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": `{Hello"{\,}" World}`, }, @@ -1107,10 +1196,10 @@ test(t, `cpu,host=serverA,region=us-east str="foo=bar",value=1.0 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": 1.0, "str": "foo=bar", // spaces in string value @@ -1123,7 +1212,7 @@ test(t, `cpu value="test\\\"" 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": `test\"`, }, @@ -1133,7 +1222,7 @@ test(t, `cpu value="test\\" 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": `test\`, }, @@ -1143,7 +1232,7 @@ test(t, `cpu value="test\\\"" 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": `test\"`, }, @@ -1153,7 +1242,7 @@ test(t, `cpu value="test\"" 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": `test"`, }, @@ -1165,10 +1254,10 @@ test(t, `cpu,host=serverA,region=us-east true=true,t=t,T=T,TRUE=TRUE,True=True,false=false,f=f,F=F,FALSE=FALSE,False=False 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "t": true, "T": true, @@ -1189,10 +1278,10 @@ test(t, `cpu,host=serverA,region=us-east value="wè" 1000000000`, NewTestPoint( "cpu", - models.Tags{ + models.NewTags(map[string]string{ "host": "serverA", "region": "us-east", - }, + }), models.Fields{ "value": "wè", }, @@ -1204,7 +1293,7 @@ test(t, `cpu value=1 -1`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": 1.0, }, @@ -1216,7 +1305,7 @@ test(t, fmt.Sprintf(`cpu value=1 %d`, models.MaxNanoTime), NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": 1.0, }, @@ -1228,7 +1317,7 @@ test(t, `cpu value=1 -9223372036854775806`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": 1.0, }, @@ -1259,7 +1348,7 @@ test(t, `cpu value=1 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": 1.0, }, @@ -1270,7 +1359,7 @@ test(t, `cpu value=-0.64 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": -0.64, }, @@ -1282,7 +1371,7 @@ test(t, `cpu value=1. 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": 1.0, }, @@ -1294,7 +1383,7 @@ test(t, `cpu value=6.632243e+06 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": float64(6632243), }, @@ -1306,7 +1395,7 @@ test(t, `cpu value=6632243i 1000000000`, NewTestPoint( "cpu", - models.Tags{}, + models.NewTags(map[string]string{}), models.Fields{ "value": int64(6632243), // if incorrectly encoded as a float, it would show up as 6.632243e+06 }, @@ -1403,7 +1492,7 @@ t.Errorf("ParsePoint() to string mismatch:\n got %v\n exp %v", got, line) } - pt = models.MustNewPoint("cpu", models.Tags{"host": "serverA", "region": "us-east"}, + pt = models.MustNewPoint("cpu", models.NewTags(map[string]string{"host": "serverA", "region": "us-east"}), models.Fields{"int": 10, "float": float64(11.0), "float2": float64(12.123), "bool": false, "str": "string val"}, time.Unix(1, 0)) @@ -1600,26 +1689,26 @@ func TestNewPointEscaped(t *testing.T) { // commas - pt := models.MustNewPoint("cpu,main", models.Tags{"tag,bar": "value"}, models.Fields{"name,bar": 1.0}, time.Unix(0, 0)) + pt := models.MustNewPoint("cpu,main", models.NewTags(map[string]string{"tag,bar": "value"}), models.Fields{"name,bar": 1.0}, time.Unix(0, 0)) if exp := `cpu\,main,tag\,bar=value name\,bar=1 0`; pt.String() != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } // spaces - pt = models.MustNewPoint("cpu main", models.Tags{"tag bar": "value"}, models.Fields{"name bar": 1.0}, time.Unix(0, 0)) + pt = models.MustNewPoint("cpu main", models.NewTags(map[string]string{"tag bar": "value"}), models.Fields{"name bar": 1.0}, time.Unix(0, 0)) if exp := `cpu\ main,tag\ bar=value name\ bar=1 0`; pt.String() != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } // equals - pt = models.MustNewPoint("cpu=main", models.Tags{"tag=bar": "value=foo"}, models.Fields{"name=bar": 1.0}, time.Unix(0, 0)) + pt = models.MustNewPoint("cpu=main", models.NewTags(map[string]string{"tag=bar": "value=foo"}), models.Fields{"name=bar": 1.0}, time.Unix(0, 0)) if exp := `cpu=main,tag\=bar=value\=foo name\=bar=1 0`; pt.String() != exp { t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp) } } func TestNewPointWithoutField(t *testing.T) { - _, err := models.NewPoint("cpu", models.Tags{"tag": "bar"}, models.Fields{}, time.Unix(0, 0)) + _, err := models.NewPoint("cpu", models.NewTags(map[string]string{"tag": "bar"}), models.Fields{}, time.Unix(0, 0)) if err == nil { t.Fatalf(`NewPoint() expected error. got nil`) } @@ -1645,19 +1734,19 @@ } func TestMakeKeyEscaped(t *testing.T) { - if exp, got := `cpu\ load`, models.MakeKey([]byte(`cpu\ load`), models.Tags{}); string(got) != exp { + if exp, got := `cpu\ load`, models.MakeKey([]byte(`cpu\ load`), models.NewTags(map[string]string{})); string(got) != exp { t.Errorf("MakeKey() mismatch.\ngot %v\nexp %v", got, exp) } - if exp, got := `cpu\ load`, models.MakeKey([]byte(`cpu load`), models.Tags{}); string(got) != exp { + if exp, got := `cpu\ load`, models.MakeKey([]byte(`cpu load`), models.NewTags(map[string]string{})); string(got) != exp { t.Errorf("MakeKey() mismatch.\ngot %v\nexp %v", got, exp) } - if exp, got := `cpu\,load`, models.MakeKey([]byte(`cpu\,load`), models.Tags{}); string(got) != exp { + if exp, got := `cpu\,load`, models.MakeKey([]byte(`cpu\,load`), models.NewTags(map[string]string{})); string(got) != exp { t.Errorf("MakeKey() mismatch.\ngot %v\nexp %v", got, exp) } - if exp, got := `cpu\,load`, models.MakeKey([]byte(`cpu,load`), models.Tags{}); string(got) != exp { + if exp, got := `cpu\,load`, models.MakeKey([]byte(`cpu,load`), models.NewTags(map[string]string{})); string(got) != exp { t.Errorf("MakeKey() mismatch.\ngot %v\nexp %v", got, exp) } @@ -1880,7 +1969,202 @@ } func TestParseKeyEmpty(t *testing.T) { - if _, _, err := models.ParseKey(""); err != nil { + if _, _, err := models.ParseKey(nil); err != nil { t.Fatalf("unexpected error: %v", err) } } + +func TestPoint_FieldIterator_Simple(t *testing.T) { + + p, err := models.ParsePoints([]byte(`m v=42i,f=42 36`)) + if err != nil { + t.Fatal(err) + } + + if len(p) != 1 { + t.Fatalf("wrong number of points, got %d, exp %d", len(p), 1) + } + + fi := p[0].FieldIterator() + + if !fi.Next() { + t.Fatal("field iterator terminated before first field") + } + + if fi.Type() != models.Integer { + t.Fatalf("'42i' should be an Integer, got %v", fi.Type()) + } + + if fi.IntegerValue() != 42 { + t.Fatalf("'42i' should be 42, got %d", fi.IntegerValue()) + } + + if !fi.Next() { + t.Fatalf("field iterator terminated before second field") + } + + if fi.Type() != models.Float { + t.Fatalf("'42' should be a Float, got %v", fi.Type()) + } + + if fi.FloatValue() != 42.0 { + t.Fatalf("'42' should be %f, got %f", 42.0, fi.FloatValue()) + } + + if fi.Next() { + t.Fatal("field iterator didn't terminate") + } +} + +func toFields(fi models.FieldIterator) models.Fields { + m := make(models.Fields) + for fi.Next() { + var v interface{} + switch fi.Type() { + case models.Float: + v = fi.FloatValue() + case models.Integer: + v = fi.IntegerValue() + case models.String: + v = fi.StringValue() + case models.Boolean: + v = fi.BooleanValue() + case models.Empty: + v = nil + default: + panic("unknown type") + } + m[string(fi.FieldKey())] = v + } + return m +} + +func TestPoint_FieldIterator_FieldMap(t *testing.T) { + + points, err := models.ParsePointsString(` +m v=42 +m v=42i +m v="string" +m v=true +m v="string\"with\"escapes" +m v=42i,f=42,g=42.314 +m a=2i,b=3i,c=true,d="stuff",e=-0.23,f=123.456 +`) + + if err != nil { + t.Fatal("failed to parse test points:", err) + } + + for _, p := range points { + exp := p.Fields() + got := toFields(p.FieldIterator()) + + if !reflect.DeepEqual(got, exp) { + t.Errorf("FieldIterator failed for %#q: got %#v, exp %#v", p.String(), got, exp) + } + } +} + +func TestPoint_FieldIterator_Delete_Begin(t *testing.T) { + points, err := models.ParsePointsString(`m a=1,b=2,c=3`) + if err != nil || len(points) != 1 { + t.Fatal("failed parsing point") + } + + fi := points[0].FieldIterator() + fi.Next() // a + fi.Delete() + + fi.Reset() + + got := toFields(fi) + exp := models.Fields{"b": float64(2), "c": float64(3)} + + if !reflect.DeepEqual(got, exp) { + t.Fatalf("Delete failed, got %#v, exp %#v", got, exp) + } +} + +func TestPoint_FieldIterator_Delete_Middle(t *testing.T) { + points, err := models.ParsePointsString(`m a=1,b=2,c=3`) + if err != nil || len(points) != 1 { + t.Fatal("failed parsing point") + } + + fi := points[0].FieldIterator() + fi.Next() // a + fi.Next() // b + fi.Delete() + + fi.Reset() + + got := toFields(fi) + exp := models.Fields{"a": float64(1), "c": float64(3)} + + if !reflect.DeepEqual(got, exp) { + t.Fatalf("Delete failed, got %#v, exp %#v", got, exp) + } +} + +func TestPoint_FieldIterator_Delete_End(t *testing.T) { + points, err := models.ParsePointsString(`m a=1,b=2,c=3`) + if err != nil || len(points) != 1 { + t.Fatal("failed parsing point") + } + + fi := points[0].FieldIterator() + fi.Next() // a + fi.Next() // b + fi.Next() // c + fi.Delete() + + fi.Reset() + + got := toFields(fi) + exp := models.Fields{"a": float64(1), "b": float64(2)} + + if !reflect.DeepEqual(got, exp) { + t.Fatalf("Delete failed, got %#v, exp %#v", got, exp) + } +} + +func TestPoint_FieldIterator_Delete_Nothing(t *testing.T) { + points, err := models.ParsePointsString(`m a=1,b=2,c=3`) + if err != nil || len(points) != 1 { + t.Fatal("failed parsing point") + } + + fi := points[0].FieldIterator() + fi.Delete() + + fi.Reset() + + got := toFields(fi) + exp := models.Fields{"a": float64(1), "b": float64(2), "c": float64(3)} + + if !reflect.DeepEqual(got, exp) { + t.Fatalf("Delete failed, got %#v, exp %#v", got, exp) + } +} + +func TestPoint_FieldIterator_Delete_Twice(t *testing.T) { + points, err := models.ParsePointsString(`m a=1,b=2,c=3`) + if err != nil || len(points) != 1 { + t.Fatal("failed parsing point") + } + + fi := points[0].FieldIterator() + fi.Next() // a + fi.Next() // b + fi.Delete() + fi.Delete() // no-op + + fi.Reset() + + got := toFields(fi) + exp := models.Fields{"a": float64(1), "c": float64(3)} + + if !reflect.DeepEqual(got, exp) { + t.Fatalf("Delete failed, got %#v, exp %#v", got, exp) + } +} diff -Nru influxdb-1.0.2+dfsg1/models/rows.go influxdb-1.1.1+dfsg1/models/rows.go --- influxdb-1.0.2+dfsg1/models/rows.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/rows.go 2016-12-06 21:36:15.000000000 +0000 @@ -1,7 +1,6 @@ package models import ( - "hash/fnv" "sort" ) @@ -11,7 +10,6 @@ Tags map[string]string `json:"tags,omitempty"` Columns []string `json:"columns,omitempty"` Values [][]interface{} `json:"values,omitempty"` - Err error `json:"err,omitempty"` } // SameSeries returns true if r contains values for the same series as o. @@ -21,7 +19,7 @@ // tagsHash returns a hash of tag key/value pairs. func (r *Row) tagsHash() uint64 { - h := fnv.New64a() + h := NewInlineFNV64a() keys := r.tagsKeys() for _, k := range keys { h.Write([]byte(k)) diff -Nru influxdb-1.0.2+dfsg1/models/statistic.go influxdb-1.1.1+dfsg1/models/statistic.go --- influxdb-1.0.2+dfsg1/models/statistic.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/statistic.go 2016-12-06 21:36:15.000000000 +0000 @@ -2,6 +2,39 @@ type Statistic struct { Name string `json:"name"` - Tags Tags `json:"tags"` + Tags map[string]string `json:"tags"` Values map[string]interface{} `json:"values"` } + +func NewStatistic(name string) Statistic { + return Statistic{ + Name: name, + Tags: make(map[string]string), + Values: make(map[string]interface{}), + } +} + +// StatisticTags is a map that can be merged with others without causing +// mutations to either map. +type StatisticTags map[string]string + +// Merge creates a new map containing the merged contents of tags and t. +// If both tags and the receiver map contain the same key, the value in tags +// is used in the resulting map. +// +// Merge always returns a usable map. +func (t StatisticTags) Merge(tags map[string]string) map[string]string { + // Add everything in tags to the result. + out := make(map[string]string, len(tags)) + for k, v := range tags { + out[k] = v + } + + // Only add values from t that don't appear in tags. + for k, v := range t { + if _, ok := tags[k]; !ok { + out[k] = v + } + } + return out +} diff -Nru influxdb-1.0.2+dfsg1/models/statistic_test.go influxdb-1.1.1+dfsg1/models/statistic_test.go --- influxdb-1.0.2+dfsg1/models/statistic_test.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/models/statistic_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,55 @@ +package models_test + +import ( + "reflect" + "testing" + + "github.com/influxdata/influxdb/models" +) + +func TestTags_Merge(t *testing.T) { + examples := []struct { + Base map[string]string + Arg map[string]string + Result map[string]string + }{ + { + Base: nil, + Arg: nil, + Result: map[string]string{}, + }, + { + Base: nil, + Arg: map[string]string{"foo": "foo"}, + Result: map[string]string{"foo": "foo"}, + }, + { + Base: map[string]string{"foo": "foo"}, + Arg: nil, + Result: map[string]string{"foo": "foo"}, + }, + { + Base: map[string]string{"foo": "foo"}, + Arg: map[string]string{"bar": "bar"}, + Result: map[string]string{"foo": "foo", "bar": "bar"}, + }, + { + Base: map[string]string{"foo": "foo", "bar": "bar"}, + Arg: map[string]string{"zoo": "zoo"}, + Result: map[string]string{"foo": "foo", "bar": "bar", "zoo": "zoo"}, + }, + { + Base: map[string]string{"foo": "foo", "bar": "bar"}, + Arg: map[string]string{"bar": "newbar"}, + Result: map[string]string{"foo": "foo", "bar": "newbar"}, + }, + } + + for i, example := range examples { + i++ + result := models.StatisticTags(example.Base).Merge(example.Arg) + if got, exp := result, example.Result; !reflect.DeepEqual(got, exp) { + t.Errorf("[Example %d] got %#v, expected %#v", i, got, exp) + } + } +} diff -Nru influxdb-1.0.2+dfsg1/monitor/service.go influxdb-1.1.1+dfsg1/monitor/service.go --- influxdb-1.0.2+dfsg1/monitor/service.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/monitor/service.go 2016-12-06 21:36:15.000000000 +0000 @@ -1,7 +1,6 @@ package monitor // import "github.com/influxdata/influxdb/monitor" import ( - "bytes" "errors" "expvar" "fmt" @@ -211,10 +210,7 @@ } statistic := &Statistic{ - Statistic: models.Statistic{ - Tags: make(map[string]string), - Values: make(map[string]interface{}), - }, + Statistic: models.NewStatistic(""), } // Add any supplied tags. @@ -279,11 +275,7 @@ // Add Go memstats. statistic := &Statistic{ - Statistic: models.Statistic{ - Name: "runtime", - Tags: make(map[string]string), - Values: make(map[string]interface{}), - }, + Statistic: models.NewStatistic("runtime"), } // Add any supplied tags to Go memstats @@ -421,7 +413,7 @@ points := make(models.Points, 0, len(stats)) for _, s := range stats { - pt, err := models.NewPoint(s.Name, s.Tags, s.Values, now) + pt, err := models.NewPoint(s.Name, models.NewTags(s.Tags), s.Values, now) if err != nil { m.Logger.Printf("Dropping point %v: %v", s.Name, err) return @@ -463,10 +455,7 @@ func (a Statistics) Len() int { return len(a) } func (a Statistics) Less(i, j int) bool { - if a[i].Name != a[j].Name { - return a[i].Name < a[j].Name - } - return bytes.Compare(a[i].Tags.HashKey(), a[j].Tags.HashKey()) < 0 + return a[i].Name < a[j].Name } func (a Statistics) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff -Nru influxdb-1.0.2+dfsg1/pkg/escape/bytes.go influxdb-1.1.1+dfsg1/pkg/escape/bytes.go --- influxdb-1.0.2+dfsg1/pkg/escape/bytes.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/pkg/escape/bytes.go 2016-12-06 21:36:15.000000000 +0000 @@ -1,6 +1,9 @@ package escape // import "github.com/influxdata/influxdb/pkg/escape" -import "bytes" +import ( + "bytes" + "strings" +) func Bytes(in []byte) []byte { for b, esc := range Codes { @@ -9,6 +12,45 @@ return in } +const escapeChars = `," =` + +func IsEscaped(b []byte) bool { + for len(b) > 0 { + i := bytes.IndexByte(b, '\\') + if i < 0 { + return false + } + + if i+1 < len(b) && strings.IndexByte(escapeChars, b[i+1]) >= 0 { + return true + } + b = b[i+1:] + } + return false +} + +func AppendUnescaped(dst, src []byte) []byte { + var pos int + for len(src) > 0 { + next := bytes.IndexByte(src[pos:], '\\') + if next < 0 || pos+next+1 >= len(src) { + return append(dst, src...) + } + + if pos+next+1 < len(src) && strings.IndexByte(escapeChars, src[pos+next+1]) >= 0 { + if pos+next > 0 { + dst = append(dst, src[:pos+next]...) + } + src = src[pos+next+1:] + pos = 0 + } else { + pos += next + 1 + } + } + + return dst +} + func Unescape(in []byte) []byte { if len(in) == 0 { return nil diff -Nru influxdb-1.0.2+dfsg1/pkg/escape/bytes_test.go influxdb-1.1.1+dfsg1/pkg/escape/bytes_test.go --- influxdb-1.0.2+dfsg1/pkg/escape/bytes_test.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/pkg/escape/bytes_test.go 2016-12-06 21:36:15.000000000 +0000 @@ -1,7 +1,9 @@ package escape import ( + "bytes" "reflect" + "strings" "testing" ) @@ -43,3 +45,24 @@ } } } + +func TestAppendUnescaped(t *testing.T) { + cases := strings.Split(strings.TrimSpace(` +normal +inv\alid +goo\"d +sp\ ace +\,\"\ \= +f\\\ x +`), "\n") + + for _, c := range cases { + exp := Unescape([]byte(c)) + got := AppendUnescaped(nil, []byte(c)) + + if !bytes.Equal(got, exp) { + t.Errorf("AppendUnescaped failed for %#q: got %#q, exp %#q", c, got, exp) + } + } + +} diff -Nru influxdb-1.0.2+dfsg1/pkg/pool/bytes.go influxdb-1.1.1+dfsg1/pkg/pool/bytes.go --- influxdb-1.0.2+dfsg1/pkg/pool/bytes.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/pkg/pool/bytes.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,42 @@ +package pool + +// Bytes is a pool of byte slices that can be re-used. Slices in +// this pool will not be garbage collected when not in use. +type Bytes struct { + pool chan []byte +} + +// NewBytes returns a Bytes pool with capacity for max byte slices +// to be pool. +func NewBytes(max int) *Bytes { + return &Bytes{ + pool: make(chan []byte, max), + } +} + +// Get returns a byte slice size with at least sz capacity. Items +// returned may not be in the zero state and should be reset by the +// caller. +func (p *Bytes) Get(sz int) []byte { + var c []byte + select { + case c = <-p.pool: + default: + return make([]byte, sz) + } + + if cap(c) < sz { + return make([]byte, sz) + } + + return c[:sz] +} + +// Put returns a slice back to the pool. If the pool is full, the byte +// slice is discarded. +func (p *Bytes) Put(c []byte) { + select { + case p.pool <- c: + default: + } +} diff -Nru influxdb-1.0.2+dfsg1/pkg/pool/generic.go influxdb-1.1.1+dfsg1/pkg/pool/generic.go --- influxdb-1.0.2+dfsg1/pkg/pool/generic.go 1970-01-01 00:00:00.000000000 +0000 +++ influxdb-1.1.1+dfsg1/pkg/pool/generic.go 2016-12-06 21:36:15.000000000 +0000 @@ -0,0 +1,40 @@ +package pool + +// Generic is a pool of types that can be re-used. Items in +// this pool will not be garbage collected when not in use. +type Generic struct { + pool chan interface{} + fn func(sz int) interface{} +} + +// NewGeneric returns a Generic pool with capacity for max items +// to be pool. +func NewGeneric(max int, fn func(sz int) interface{}) *Generic { + return &Generic{ + pool: make(chan interface{}, max), + fn: fn, + } +} + +// Get returns a item from the pool or a new instance if the pool +// is empty. Items returned may not be in the zero state and should +// be reset by the caller. +func (p *Generic) Get(sz int) interface{} { + var c interface{} + select { + case c = <-p.pool: + default: + c = p.fn(sz) + } + + return c +} + +// Put returns an item back to the pool. If the pool is full, the item +// is discarded. +func (p *Generic) Put(c interface{}) { + select { + case p.pool <- c: + default: + } +} diff -Nru influxdb-1.0.2+dfsg1/services/admin/assets/index.html influxdb-1.1.1+dfsg1/services/admin/assets/index.html --- influxdb-1.0.2+dfsg1/services/admin/assets/index.html 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/services/admin/assets/index.html 2016-12-06 21:36:15.000000000 +0000 @@ -88,7 +88,7 @@
- +
diff -Nru influxdb-1.0.2+dfsg1/services/admin/assets/js/admin.js influxdb-1.1.1+dfsg1/services/admin/assets/js/admin.js --- influxdb-1.0.2+dfsg1/services/admin/assets/js/admin.js 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/services/admin/assets/js/admin.js 2016-12-06 21:36:15.000000000 +0000 @@ -352,6 +352,14 @@ } } +var truncateVersion = function (version) { + var parts = version.split(".") + if (parts.length > 2) { + parts = parts.slice(0, 2) + } + return parts.join(".") +} + var getClientVersion = function () { var query = $.get(window.location.origin + window.location.pathname); @@ -360,8 +368,8 @@ query.done(function (data, status, xhr) { var version = xhr.getResponseHeader('X-InfluxDB-Version'); if (version.indexOf("unknown") == -1) { - version = 'v' + version; - console.log('got client version '+version); + console.log('got client version v'+version); + version = 'v' + truncateVersion(version); $('#influxdb-doc-link').attr('href', 'https://docs.influxdata.com/influxdb/'+version+'/introduction/getting_started/'); } $('.influxdb-client-version').html(version); diff -Nru influxdb-1.0.2+dfsg1/services/admin/service.go influxdb-1.1.1+dfsg1/services/admin/service.go --- influxdb-1.0.2+dfsg1/services/admin/service.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/services/admin/service.go 2016-12-06 21:36:15.000000000 +0000 @@ -42,6 +42,7 @@ // Open starts the service func (s *Service) Open() error { s.logger.Printf("Starting admin service") + s.logger.Println("DEPRECATED: This plugin is deprecated as of 1.1.0 and will be removed in a future release") // Open listener. if s.https { diff -Nru influxdb-1.0.2+dfsg1/services/admin/statik/statik.go influxdb-1.1.1+dfsg1/services/admin/statik/statik.go --- influxdb-1.0.2+dfsg1/services/admin/statik/statik.go 2016-10-05 19:19:17.000000000 +0000 +++ influxdb-1.1.1+dfsg1/services/admin/statik/statik.go 2016-12-06 21:36:15.000000000 +0000 @@ -5,6 +5,6 @@ ) func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00README.mdPlease note that these files are embedded into the `influxd` binary using the\n[statik](https://github.com/rakyll/statik) tool. `go generate` needs to be run\nwhenever there are changes made to files in this directory. See the admin\ninterface readme for more information.\nPK\x07\x08\xeb\xa78$\x0e\x01\x00\x00\x0e\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00css/admin.cssbody {\n padding-top: 70px;\n /* Required padding for .navbar-fixed-top. Remove if using .navbar-static-top. Change if height of navigation changes. */\n}\n\nhtml,\nbody {\n height: 100%;\n /* The html and body elements cannot have any padding or margin. */\n}\n\ncode {\n display: block;\n}\n\n#settings {\n display: none;\n}\n\n#settings form > div {\n margin-right: 20px;\n}\n\n#settings form input#port {\n width: 80px;\n}\n\n#settings form label {\n padding-right: 5px;\n}\n\ndiv#content {\n margin-bottom: -10px;\n}\n\ndiv#table h2 {\n color: #999;\n margin-top: -8px;\n font-size: 16px\n}\n\ntextarea#content-data {\n font-family: \"Courier New\";\n height: 200px;\n}\n\ndiv#query-alerts {\n margin-top: 30px;\n}\n\ndiv#modal-error, div#modal-success, div#query-error, div#query-success {\n display: none; \n}\n\n/* Wrapper for page content to push down footer */\n#wrap {\n min-height: 100%;\n height: auto !important;\n height: 100%;\n /* Negative indent footer by it's height */\n margin: 0 auto -60px;\n}\n\n/* Set the fixed height of the footer here */\n#push,\n#footer {\n height: 60px;\n}\n#footer {\n background-color: #f5f5f5;\n border-top: 1px solid #dfdfdf;\n}\n\n#footer p {\n margin: 20px 0;\n}\n\n/* Lastly, apply responsive CSS fixes as necessary */\n@media (max-width: 767px) {\n #footer {\n margin-left: -20px;\n margin-right: -20px;\n padding-left: 20px;\n padding-right: 20px;\n }\n}\n\nPK\x07\x08\x9c\x84U>\x8e\x05\x00\x00\x8e\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00css/bootstrap.css/*!\n * Bootstrap v3.3.4 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\nhtml {\n font-family: sans-serif;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n margin: .67em 0;\n font-size: 2em;\n}\nmark {\n color: #000;\n background: #ff0;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\nsup {\n top: -.5em;\n}\nsub {\n bottom: -.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n height: 0;\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n margin: 0;\n font: inherit;\n color: inherit;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n padding: 0;\n border: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n -webkit-appearance: textfield;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n padding: .35em .625em .75em;\n margin: 0 2px;\n border: 1px solid #c0c0c0;\n}\nlegend {\n padding: 0;\n border: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-spacing: 0;\n border-collapse: collapse;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important;\n text-shadow: none !important;\n background: transparent !important;\n -webkit-box-shadow: none !important;\n box-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n select {\n background: #fff !important;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\2a\";\n}\n.glyphicon-plus:before {\n content: \"\\2b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n display: inline-block;\n max-width: 100%;\n height: auto;\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all .2s ease-in-out;\n -o-transition: all .2s ease-in-out;\n transition: all .2s ease-in-out;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n padding: .2em;\n background-color: #fcf8e3;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n margin-left: -5px;\n list-style: none;\n}\n.list-inline > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n overflow: hidden;\n clear: left;\n text-align: right;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid #eee;\n border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n color: #333;\n word-break: break-all;\n word-wrap: break-word;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n.row {\n margin-right: -15px;\n margin-left: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n display: table-column;\n float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n display: table-cell;\n float: none;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n min-height: .01%;\n overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n vertical-align: middle;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n min-height: 34px;\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-right: 0;\n padding-left: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.form-group-sm .form-control {\n height: 30px;\n line-height: 30px;\n}\ntextarea.form-group-sm .form-control,\nselect[multiple].form-group-sm .form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.form-group-lg .form-control {\n height: 46px;\n line-height: 46px;\n}\ntextarea.form-group-lg .form-control,\nselect[multiple].form-group-lg .form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n background-color: #f2dede;\n border-color: #a94442;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n padding-top: 7px;\n margin-top: 0;\n margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n padding-top: 7px;\n margin-bottom: 0;\n text-align: right;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 14.333333px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n }\n}\n.btn {\n display: inline-block;\n padding: 6px 12px;\n margin-bottom: 0;\n font-size: 14px;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n -ms-touch-action: manipulation;\n touch-action: manipulation;\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n outline: 0;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n pointer-events: none;\n cursor: not-allowed;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n opacity: .65;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus,\n.btn-default.focus,\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary.focus,\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:hover,\n.btn-success:focus,\n.btn-success.focus,\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:hover,\n.btn-info:focus,\n.btn-info.focus,\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning.focus,\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger.focus,\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n font-weight: normal;\n color: #337ab7;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity .15s linear;\n -o-transition: opacity .15s linear;\n transition: opacity .15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-timing-function: ease;\n -o-transition-timing-function: ease;\n transition-timing-function: ease;\n -webkit-transition-duration: .35s;\n -o-transition-duration: .35s;\n transition-duration: .35s;\n -webkit-transition-property: height, visibility;\n -o-transition-property: height, visibility;\n transition-property: height, visibility;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n font-size: 14px;\n text-align: left;\n list-style: none;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, .15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n color: #262626;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n background-color: #337ab7;\n outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n content: \"\";\n border-top: 0;\n border-bottom: 4px solid;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n right: 0;\n left: auto;\n }\n .navbar-right .dropdown-menu-left {\n right: auto;\n left: 0;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555;\n text-align: center;\n background-color: #eee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n margin-left: -1px;\n}\n.nav {\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eee;\n}\n.nav > li.disabled > a {\n color: #777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777;\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eee #eee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555;\n cursor: default;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n padding-right: 15px;\n padding-left: 15px;\n overflow-x: visible;\n -webkit-overflow-scrolling: touch;\n border-top: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-right: 0;\n padding-left: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n height: 50px;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-top: 8px;\n margin-right: 15px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n padding: 10px 15px;\n margin-top: 8px;\n margin-right: -15px;\n margin-bottom: 8px;\n margin-left: -15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-right: 15px;\n margin-left: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n color: #fff;\n background-color: #080808;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n padding: 0 5px;\n color: #ccc;\n content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n color: #777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n margin-left: -1px;\n line-height: 1.42857143;\n color: #337ab7;\n text-decoration: none;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n color: #23527c;\n background-color: #eee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 2;\n color: #fff;\n cursor: default;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777;\n cursor: not-allowed;\n background-color: #fff;\n border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n text-align: center;\n list-style: none;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777;\n cursor: not-allowed;\n background-color: #fff;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n background-color: #777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding: 30px 15px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding: 48px 0;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-right: 60px;\n padding-left: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border .2s ease-in-out;\n -o-transition: border .2s ease-in-out;\n transition: border .2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-right: auto;\n margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@-o-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n height: 20px;\n margin-bottom: 20px;\n overflow: hidden;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n}\n.progress-bar {\n float: left;\n width: 0;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n -webkit-transition: width .6s ease;\n -o-transition: width .6s ease;\n transition: width .6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n -webkit-background-size: 40px 40px;\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n padding-left: 0;\n margin-bottom: 20px;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\na.list-group-item:focus {\n color: #555;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n color: #777;\n cursor: not-allowed;\n background-color: #eee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\na.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\na.list-group-item-success.active:hover,\na.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\na.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\na.list-group-item-info.active:hover,\na.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\na.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\na.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-right: 15px;\n padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n margin-bottom: 0;\n border: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, .15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n filter: alpha(opacity=20);\n opacity: .2;\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n filter: alpha(opacity=50);\n opacity: .5;\n}\nbutton.close {\n -webkit-appearance: none;\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transition: -webkit-transform .3s ease-out;\n -o-transition: -o-transform .3s ease-out;\n transition: transform .3s ease-out;\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, .2);\n border-radius: 6px;\n outline: 0;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.modal-backdrop.in {\n filter: alpha(opacity=50);\n opacity: .5;\n}\n.modal-header {\n min-height: 16.42857143px;\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 12px;\n font-weight: normal;\n line-height: 1.4;\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.tooltip.in {\n filter: alpha(opacity=90);\n opacity: .9;\n}\n.tooltip.top {\n padding: 5px 0;\n margin-top: -3px;\n}\n.tooltip.right {\n padding: 0 5px;\n margin-left: 3px;\n}\n.tooltip.bottom {\n padding: 5px 0;\n margin-top: 3px;\n}\n.tooltip.left {\n padding: 0 5px;\n margin-left: -3px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n text-decoration: none;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n right: 5px;\n bottom: 0;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n white-space: normal;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, .2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n padding: 8px 14px;\n margin: 0;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n content: \"\";\n border-width: 10px;\n}\n.popover.top > .arrow {\n bottom: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-color: #999;\n border-top-color: rgba(0, 0, 0, .25);\n border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n bottom: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-color: #fff;\n border-bottom-width: 0;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-right-color: #999;\n border-right-color: rgba(0, 0, 0, .25);\n border-left-width: 0;\n}\n.popover.right > .arrow:after {\n bottom: -10px;\n left: 1px;\n content: \" \";\n border-right-color: #fff;\n border-left-width: 0;\n}\n.popover.bottom > .arrow {\n top: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999;\n border-bottom-color: rgba(0, 0, 0, .25);\n}\n.popover.bottom > .arrow:after {\n top: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999;\n border-left-color: rgba(0, 0, 0, .25);\n}\n.popover.left > .arrow:after {\n right: 1px;\n bottom: -10px;\n content: \" \";\n border-right-width: 0;\n border-left-color: #fff;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n.carousel-inner > .item {\n position: relative;\n display: none;\n -webkit-transition: .6s ease-in-out left;\n -o-transition: .6s ease-in-out left;\n transition: .6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform .6s ease-in-out;\n -o-transition: -o-transform .6s ease-in-out;\n transition: transform .6s ease-in-out;\n\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000;\n perspective: 1000;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n left: 0;\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n left: 0;\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n left: 0;\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 15%;\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n filter: alpha(opacity=50);\n opacity: .5;\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control.right {\n right: 0;\n left: auto;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n color: #fff;\n text-decoration: none;\n filter: alpha(opacity=90);\n outline: 0;\n opacity: .9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n margin-top: -10px;\n font-family: serif;\n line-height: 1;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n border: 1px solid #fff;\n border-radius: 10px;\n}\n.carousel-indicators .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -15px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -15px;\n }\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-footer:before,\n.modal-footer:after {\n display: table;\n content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */\nPK\x07\x08\xbeO[\x0b6)\x02\x006)\x02\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00css/dropdowns-enhancement.css.dropdown-menu > li > label {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > label:hover,\n.dropdown-menu > li > label:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > li > input:checked ~ label,\n.dropdown-menu > li > input:checked ~ label:hover,\n.dropdown-menu > li > input:checked ~ label:focus,\n.dropdown-menu > .active > label,\n.dropdown-menu > .active > label:hover,\n.dropdown-menu > .active > label:focus {\n color: #ffffff;\n text-decoration: none;\n outline: 0;\n background-color: #428bca;\n}\n.dropdown-menu > li > input[disabled] ~ label,\n.dropdown-menu > li > input[disabled] ~ label:hover,\n.dropdown-menu > li > input[disabled] ~ label:focus,\n.dropdown-menu > .disabled > label,\n.dropdown-menu > .disabled > label:hover,\n.dropdown-menu > .disabled > label:focus {\n color: #999999;\n}\n.dropdown-menu > li > input[disabled] ~ label:hover,\n.dropdown-menu > li > input[disabled] ~ label:focus,\n.dropdown-menu > .disabled > label:hover,\n.dropdown-menu > .disabled > label:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.dropdown-menu > li > label {\n margin-bottom: 0;\n cursor: pointer;\n}\n.dropdown-menu > li > input[type=\"radio\"],\n.dropdown-menu > li > input[type=\"checkbox\"] {\n display: none;\n position: absolute;\n top: -9999em;\n left: -9999em;\n}\n.dropdown-menu > li > label:focus,\n.dropdown-menu > li > input:focus ~ label {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu.pull-top {\n bottom: 100%;\n top: auto;\n margin: 0 0 2px;\n -webkit-box-shadow: 0 -6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 -6px 12px rgba(0, 0, 0, 0.175);\n}\n.dropdown-menu.pull-center {\n right: 50%;\n left: auto;\n}\n.dropdown-menu.pull-middle {\n right: 100%;\n margin: 0 2px 0 0;\n box-shadow: -5px 0 10px rgba(0, 0, 0, 0.2);\n left: auto;\n}\n.dropdown-menu.pull-middle.pull-right {\n right: auto;\n left: 100%;\n margin: 0 0 0 2px;\n box-shadow: 5px 0 10px rgba(0, 0, 0, 0.2);\n}\n.dropdown-menu.pull-middle.pull-center {\n right: 50%;\n margin: 0;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);\n}\n.dropdown-menu.bullet {\n margin-top: 8px;\n}\n.dropdown-menu.bullet:before {\n width: 0;\n height: 0;\n content: '';\n display: inline-block;\n position: absolute;\n border-color: transparent;\n border-style: solid;\n -webkit-transform: rotate(360deg);\n border-width: 0 7px 7px;\n border-bottom-color: #cccccc;\n border-bottom-color: rgba(0, 0, 0, 0.15);\n top: -7px;\n left: 9px;\n}\n.dropdown-menu.bullet:after {\n width: 0;\n height: 0;\n content: '';\n display: inline-block;\n position: absolute;\n border-color: transparent;\n border-style: solid;\n -webkit-transform: rotate(360deg);\n border-width: 0 6px 6px;\n border-bottom-color: #ffffff;\n top: -6px;\n left: 10px;\n}\n.dropdown-menu.bullet.pull-right:before {\n left: auto;\n right: 9px;\n}\n.dropdown-menu.bullet.pull-right:after {\n left: auto;\n right: 10px;\n}\n.dropdown-menu.bullet.pull-top {\n margin-top: 0;\n margin-bottom: 8px;\n}\n.dropdown-menu.bullet.pull-top:before {\n top: auto;\n bottom: -7px;\n border-bottom-width: 0;\n border-top-width: 7px;\n border-top-color: #cccccc;\n border-top-color: rgba(0, 0, 0, 0.15);\n}\n.dropdown-menu.bullet.pull-top:after {\n top: auto;\n bottom: -6px;\n border-bottom: none;\n border-top-width: 6px;\n border-top-color: #ffffff;\n}\n.dropdown-menu.bullet.pull-center:before {\n left: auto;\n right: 50%;\n margin-right: -7px;\n}\n.dropdown-menu.bullet.pull-center:after {\n left: auto;\n right: 50%;\n margin-right: -6px;\n}\n.dropdown-menu.bullet.pull-middle {\n margin-right: 8px;\n}\n.dropdown-menu.bullet.pull-middle:before {\n top: 50%;\n left: 100%;\n right: auto;\n margin-top: -7px;\n border-right-width: 0;\n border-bottom-color: transparent;\n border-top-width: 7px;\n border-left-color: #cccccc;\n border-left-color: rgba(0, 0, 0, 0.15);\n}\n.dropdown-menu.bullet.pull-middle:after {\n top: 50%;\n left: 100%;\n right: auto;\n margin-top: -6px;\n border-right-width: 0;\n border-bottom-color: transparent;\n border-top-width: 6px;\n border-left-color: #ffffff;\n}\n.dropdown-menu.bullet.pull-middle.pull-right {\n margin-right: 0;\n margin-left: 8px;\n}\n.dropdown-menu.bullet.pull-middle.pull-right:before {\n left: -7px;\n border-left-width: 0;\n border-right-width: 7px;\n border-right-color: #cccccc;\n border-right-color: rgba(0, 0, 0, 0.15);\n}\n.dropdown-menu.bullet.pull-middle.pull-right:after {\n left: -6px;\n border-left-width: 0;\n border-right-width: 6px;\n border-right-color: #ffffff;\n}\n.dropdown-menu.bullet.pull-middle.pull-center {\n margin-left: 0;\n margin-right: 0;\n}\n.dropdown-menu.bullet.pull-middle.pull-center:before {\n border: none;\n display: none;\n}\n.dropdown-menu.bullet.pull-middle.pull-center:after {\n border: none;\n display: none;\n}\n.dropdown-submenu {\n position: relative;\n}\n.dropdown-submenu > .dropdown-menu {\n top: 0;\n left: 100%;\n margin-top: -6px;\n margin-left: -1px;\n border-top-left-radius: 0;\n}\n.dropdown-submenu > a:before {\n display: block;\n float: right;\n width: 0;\n height: 0;\n content: \"\";\n margin-top: 6px;\n margin-right: -8px;\n border-width: 4px 0 4px 4px;\n border-style: solid;\n border-left-style: dashed;\n border-top-color: transparent;\n border-bottom-color: transparent;\n}\n@media (max-width: 767px) {\n .navbar-nav .dropdown-submenu > a:before {\n margin-top: 8px;\n border-color: inherit;\n border-style: solid;\n border-width: 4px 4px 0;\n border-left-color: transparent;\n border-right-color: transparent;\n }\n .navbar-nav .dropdown-submenu > a {\n padding-left: 40px;\n }\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a,\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > label {\n padding-left: 35px;\n }\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a,\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > label {\n padding-left: 45px;\n }\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > label {\n padding-left: 55px;\n }\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > label {\n padding-left: 65px;\n }\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a,\n .navbar-nav > .open > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > label {\n padding-left: 75px;\n }\n}\n.navbar-default .navbar-nav .open > .dropdown-menu > .dropdown-submenu.open > a,\n.navbar-default .navbar-nav .open > .dropdown-menu > .dropdown-submenu.open > a:hover,\n.navbar-default .navbar-nav .open > .dropdown-menu > .dropdown-submenu.open > a:focus {\n background-color: #e7e7e7;\n color: #555555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open > .dropdown-menu > .dropdown-submenu.open > a:before {\n border-top-color: #555555;\n }\n}\n.navbar-inverse .navbar-nav .open > .dropdown-menu > .dropdown-submenu.open > a,\n.navbar-inverse .navbar-nav .open > .dropdown-menu > .dropdown-submenu.open > a:hover,\n.navbar-inverse .navbar-nav .open > .dropdown-menu > .dropdown-submenu.open > a:focus {\n background-color: #080808;\n color: #ffffff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open > .dropdown-menu > .dropdown-submenu.open > a:before {\n border-top-color: #ffffff;\n }\n}\nPK\x07\x08\x9a\x90:SN \x00\x00N \x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00fonts/glyphicons-halflings-regular.eot\x9fN\x00\x00AM\x00\x00\x02\x00\x02\x00\x04\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x01\x00\x90\x01\x00\x00\x04\x00LP\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00'\x12\x7f,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00G\x00L\x00Y\x00P\x00H\x00I\x00C\x00O\x00N\x00S\x00 \x00H\x00a\x00l\x00f\x00l\x00i\x00n\x00g\x00s\x00\x00\x00\x0e\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00\x00\x00x\x00V\x00e\x00r\x00s\x00i\x00o\x00n\x00 \x001\x00.\x000\x000\x009\x00;\x00P\x00S\x00 \x000\x000\x001\x00.\x000\x000\x009\x00;\x00h\x00o\x00t\x00c\x00o\x00n\x00v\x00 \x001\x00.\x000\x00.\x007\x000\x00;\x00m\x00a\x00k\x00e\x00o\x00t\x00f\x00.\x00l\x00i\x00b\x002\x00.\x005\x00.\x005\x008\x003\x002\x009\x00\x00\x008\x00G\x00L\x00Y\x00P\x00H\x00I\x00C\x00O\x00N\x00S\x00 \x00H\x00a\x00l\x00f\x00l\x00i\x00n\x00g\x00s\x00 \x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00\x00\x00\x00\x00BSGP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\xa9\xdc\x00M\x13\x00M\x19\x00F\xee\x14\xcd\xe9\x8c\xcf\xd2\x11\xd9\xa3(u\x1b\xca\x8c<\x010D\xe3B/X\x0d\xefN\xef\x0b\x88\x00CC\xea^\xc7\x05\x0crmR2sk\xc9\xcbPJ\"5+\x96gl\xe9W*i\xd5W\x96/E\xee\x91\x9c\xd3\x054#\xac\xd4\xa3U\xa6~\xb2f\x10\x89\x91\x1bUD\xdc\xc4\xb9\xf7\x88\xab\xb1\xe0J\xb71\xe1/!\xfe\xfe/\x9e\xba\xcas\xaa\x027\x19\x92\x93k\x8a\x95\x94\x07\x06(\xba\x88\xa1h\x1fN\xf8\xe98o\x90\xedd$yq\x8e\xb91\xb3\xe2\xd69\x16\x83@\x11-\x89\x82HG\x92\x01\xf4\x18\xb5S\"\xf8Fj\xf4\x04\xd8\xa06C3\x94\xa4&\x9e\x87\xc1\x1e\xf8\xaaW51\xc1\xd3\x1b\xdc\xd7B\x9f\xafa\xcb\xeaQaR\x86U/\xf5\xb6{*\xbf\x82\xcb\xef\x00\x82=\x96@d\xf4\xf8h$\xa1\x1e1\xc9T\xdb\x97nc+c\x92\xdeA\xa1\xa7\xbc \x17\x95Z\xc9\x80\xa4@Q\xd1c\xada\x1a\x87\xd5\xdel\xf7\x902>\xcaK\xb0\xc8\x04\x01m\xf3' \x0b\x93\xcb\x19C\x87HM\xc4\xacfB\x89X\x8d,\xbeY\x01\x17\xf2\xc2p\xa8e\xa2\x90\n\xee\x8d\xb8U\xf8\xd8\x01\x1e*\xd2\x94\x1az\xff\nm\x82\xcb\xcbi\x16\x10O1nE\xc6.\x10\x9b\x84\xe4\x0dhx!aC\nXT\xda\x14V\xa2\xc5\x16\xa9\xc2\x8b\x96\x0c\x97\x07\xe9R\x1d\xa5\x9a\x1e%\xa5\x04\x04|I\xe4\xa0H\xf0\x90\xc5\xd5P\x835\"\xc5b\x92N\xb2\x10\x11\xb5=\xe2\xf8\x83r\xd9/_\xe5R\x8c\x9b\x94\x99_\x0b\xe0%\xd2\x84\x8duz\xc9\xe9\xd2\x98\xd65\x922\xc4\xa1\xd2\xe3\x05P\xda)\x9e\xd4\xfe\x11\x9e\x1b\xc6\xc3F\x837S\x8b\x01q\x84F\xc0{n\xe1i\x14a\x81\x02\xb7\xb8@D\x11\xd0s\x88;\x9a\x18\x1f}9\x1b\xe2\xac\xa5?\xc5\xba\x91\x06\x19\xa7\xc2\x0b\x0cR{\xa6Tk\xed;\xde\xb5\xc7\x9c\xd7U\\N\x9eZ\xf8\x9bQ-\xbb^\xd4s\x90\x7f7\xf2f\x0b0\x19\x98\xca\xc6S3A\x0c\xdc\x0d_n\x90\x81`W\x1c7P\x7f\x12p\x98\xbb\xf4\xe0\x08i\xab\xed\xb3!\xf0g\xd8/\xe0_p\xbb\xc1\xd2\x04Z\x80-=\xc3\xd7\xa5~WZ#/\xe14 KF\x00`\xb4 \xbb\x8c\x01z\xdf\x02\xd20\x07\xdb| D\x82\x06\x14\xd1\xb5\x00\xec\x00\x82&d\xc3\xa4I\x89\xb4\x8e\xfc\xc3\x8f\xc1;\xb7M\xec\x94{'\xb6om\x86\x94m\xa2\x0bI\x0b\x11\x06!w\x1ci9|H:\xa7\xdb\xa7\xc0\xbb\xe7\xf7\xca\xfe\xbe{\x15\xfb~\xf6\xb9\xfdq\x04\xba\xb8\xa9O\xf8\xe5\xf4\xee\xa9\xa0\x0f\xfa\x9b,\x98 \x82L]&\x84J0\xf1\x95\xd99/\x03\xed\x0f9&\xccY\xf8\x0c\xe8\x93\xb0{;\xf7\xfa'\xc03`\x1c\x92e\x00\x7f@v\x14H\x0f\x84y\x08DZ$\xba\x00\x843\x81\xcb\x03\x88Dx28\x0c\x04\x05\x83W\x80 Cx5x\x18\x08w\x07\x82B`\xa3$C$'\xe3\xcaEl\x85\x1cy\xa0\xd5h\xbf\xeb\x1c\xd4\x80\x0d\x0bDJ\n$(p\x9d\x06\xbd\x07\xeeQA\x94A\xdc\x89A\x96@'\xc7$\x0dh\x03p\x1c\xca0\xceV\x120 `\x9d\xbas\xbe\xaae\xd2$\xc94$\"t2=f\xb4\x984\x84A\x84{Tk\x96\x070|r\x18H\xa4\xf6\x10\xc4\xd0\x02\xa3\xef`\x1bL&\xb1\xb4s\xd4h\xa6]\x01\x94\xa7A<\xa3\x1a\xa1\x8b\xb2`R\xb4'\xa3\x02\x95!\x83\x8b\x811N\xa6\x01;\xa3\x12_\x8at3\xdb#\xa0 \xe2\xf2\xeb\xfa\x18\xd8\xeaV\xe3\x05\xea\x0b*ve\xd1F`E\x7f O$\x8e{)\xd9W=p:\xae\xde\xd6\x11F`\x8a\xbe2\x1a\xc6\xc42\xda\x93C\xeb\xc1\x8c\xd2^\xd7.\xca\x15\xc4\x87\x03\x98\xa1\xf8\x96\xf8G\x08\xfe<\xfb.p\x1e\xe7Ne2\xea\x8b\xef\xd6\xb4\xba\xde+Y\xecs\x16\xdbl:\xc2\xc3\xcb\xbc\xef\xb5\x0c\xdc\xabu5\xa9\xa6\xde\xee\xd0t\xc0u\x95^8\xbe\xcc6\xe8\xf3\x1f\x07\xc8\x84Tmy\xf0Q\xc9%\x16\xfeu~\xf4\xf2\x9a%~1r\xd2\x98a\xfdw\xdf\x9a^\x90\xf9_\xa9Z\xa3\x8dZ\x9da\xa2\x83\xb20!\xd9\xe8\x05\x8d\xa1\xb7\xfaN\xf6`\xa5.\x8e\x0duq\xc0\xb1\xe7\xeaYB\xa5\\\x99\x1b\xa8\xf3\x85\x84\xca\x11\xe1\xa8\x80\xd4\x15\xea\x85\x13[\x07e\xf0\x8b\xee\xee\xfe:@\xa0\xeaJ'E\x17\xdb\x81,\xaf3\x1f\x1dubj@\x8dp\xa8\xc1\xc6\xe4\x17\xf0\x13\xb4f\xa8\xc9\xdf\x15\xf3\x7f\xee\xb5\xb7eW9( \xf3\x1b\xba\xe5\x02\xa0\xb4\xde\x85\x89\xb3\xe6=\x8b\x17l\x94G\x1e\xa6\xe0\x017\x12g\x10j\x1a \xe2S\x83M6\xc6\x01\xb0\xa0\xf40\x83\xff9\xf2\xa7\x96O\xcb\x91\xa8\x9d\xfc\xed\x8dl\xa7\xaeB\xbc\x0e\x07a\xaa\xdd\x81\xf2\xaf\xa0\x0b\x83<\xa6\xe7\x02\x01\x9e\xc7B\xd5\x99(\x04VRAp\xa1f\xf9^\xb0\xfa\xaf+g9\xa0q\xd3\xdd\x0e\xb9\x8d\x8aM\xc6t\x1c\x18]\x04\x1d\xbb\xd8\xaa\x81p\xebE\x8d\x95r\x07@]\x87@\x1e\xf3\x0f\xa9V\x8d\x9fkV\xa5\n\x05u\x13\xea\x1a\xe4d\xe9^\xd1\x11X \x8d\x15\xe5\x96\x06\x97R@?E\x1d\xd5\xf6Y2\xf4\xa8\x98\x1c\xc9\xef]#\xe0\xc7\xbc\x9a4\x03\xc0J\xde\xe5K\xf6\xc1\x07\xe4\xd6'\xc3\xc1\xbed\xb2\xe2PC|m\xe3m\xe5n\xe4#\xbe\x82\x10\x07$+48u'\x11\x85\x90\xe7e&\xfb\xbf\x80[n[L\x11\xe1\xc8\x1d\xf9\x92\x9e\xb1%{BCD\xdaL:\x01^!\xa0\x8b\x82\xd3b\xc6\x99:&\xc9\xff\x0f\x88\xee\x82g3\x93-3\xd0\xf8u\xb4\xe8\x7f\xad\xc7\xe6\xd0\xf0\xb9\x83b\x0diLZ\xe9\xda\x82W\x82FS\xc9\xe4Id\xcd\x02\xf1\xa16.\x91k5P\xee\x84\x04l7\x9e7\xfcUz\x92T:N\xfdN\xa1\x91\x97.\xfd\"\x80\xaa\xe5\xfc)\x89\xc5\x19\x97\xec\x92['\xdf|U\"\x0fA\x1c\x83\x04\x80\xb3\x97\x82I\x95\x81\xdbv\xa9w\xd0\xdb\xd8p\xeb\x99\xed\xadt\xb9dk\x82\x88\x9e9\xd8\x08\x9b\x8a\xe5\xab\xab\xcd9\x00n\xa8D\x8bmq\xb9\x977I\x18|6\x9bK\x03bc\x83]\xb6\x06M\xf4\x93\x19\x12\xa9\xb2\xc4\xce\xf7\x97\xe8\xb6\x12B\x8dA\x90\x80B\xf8\xc8\xaa\x06\x00_\xf4J\xbaT\x0c\xd9\xfc\x08\x18\x01q \xd0\x07 \x1e6@\x97\xa7\x84\xb8F\x8d\x97\x87\x83\x9ehd`G\xae\x8fT\xeb\x14\xf1\xb7:M\x1e\x7f\xc57'\xe0\x85L,\xe9\x17Ih\x97\xc6FP \xbb\xca~j\x00\xbd\x06\x8a\x8c\xed\xc4\x0c\xac$\xc2\xa1\xc2\x84 \xc43\x99hA\x13\xdd\xe4\x00\x81\x92-S\x8c^\xfb\xda\x86\x90\x85\x06\xd0\xe4-%qe\xcf\x14\xec\xeb~\xc0\xc6Qq\xab\xa7\x16\xacln\"i\xbe\x9e\x07&\x90\x91\x07\xe6\xd1Qe?Fl\x0eK\xef\xa8\"\xfaAs\x14\xc0(\xdd3\x1dY;\"\xa1L\x9e\xda\xd4e\x80t\xe5\x1c'\xc4RzM\x1a\x9c\xaa1\x0c\x110\xa8{=\xe6\x90\xf7)\x9e\x80\x0b\xb3K\xa0%\x8f$C\n\xc2\xf8\x919\x8aM\xf0\xf6\xbc\xeb\xbc4c\x01 \xea\x80Eotj\xcd\xc2V\xa7GD\x8e)l\xf18\x93\xaf,\x98\\w\xc0\xa5\xe0\x0b!\x00%$\xbf\xd73t\xc9 T\x12B\x1az\x92\x9e\xd2\xb4 iU\x1aJ\xd2\xdd\x12[\xa2\xc7x\x12g\x13d\x1c\x84\x1eBr\xef$\xc5\x18!eq\x88\x81\x92\"J>\xe0\x10\xa3 \x0c)\\\x9d~\xa1\x82\x8a\x893\x08\x90\x0e(\x08^\x0d\xe2\xa0R\xc2\x808#>\xd6\x07b\x9b\x05\xe4H\x80\xe2G'7_\x0cf\xd3\xabc\xce\xbatD\x00oAA\xdf\x83\x86(q\x99B<\x16\xfd`\xc7\x03\xad\x1c`V\x88\xfc\xf8\xe9\xce\xab\x94\xa9\xd6\x98\x19\xc2*\xfab\xde\xcfu\x8b\x14P\xad4\x13v@\x97+\x95\xca\x04.\x08\x8f\x92\xeeQ\xe5\xd4\xa5$V\x82\x12\xa1\x19\x95\xed@C0\n\x0b\xedR\xa2\xd3\x1c\x04\xdc\x90P[\x91\x1d\x11z:X\xa6H\x18#e\xe4\xc1\x0b\x02\xf2s\xa0>?\xfa\x05E\xc8WO>@\x0eI\xd8$|s\xac\x9ei\x1a\xe2\nE\x02\x12S\xa5\xb2)0A\x8c?\x16\xa39\x95ab,\xb6\x8d@K\x9a\xf1\xcc\xa9o&\xee\x04\xfe\xfc\x0e\x88\xacQ\xb4%\xac\x0c\xcf\x9eLu+\x9b\n\xc2+\x90H|\xcc\xc6\x90?\xb4\x16NK\xcc\x1b4\x8c\xc6\x17\x92\xd3CnPt\xe8\xb3\x0d'OT\xf2\x9c\xd2.j5\xe0\xc4\xb48\xc8\xdcv\xb6w\xd6\x9c\x90\xab\x12I\xa5\x12&\x95+\xdf`\x02\xbc\x8ay\x18S\x9d\x90caO\x11[#\xa1g\xb0\xa7\x08Q\xa7\x9c\x80\xb8\xdad\xaa\x17[\xeeK\xbdI\xe7\x9f\x97`\xf4\x07\xc4\x8cLP\xfd\xd3\x18\xb8 #\xb0\xc1\x9c\xbd \xa9)2\xd27\x16aT\x83\x7f\xe4\x16\xebi@c\\\xde\x90\x91\xee\x0b\xc2\xe2\xc80n\xeaC\xbbp\xf2\x10\xdf\x96\xe9\x81\x8b4\xcd\xb5\x8e\x90x\xf6*\xf1\xcb\xd0R\x94z\xd5\x0eY\xe2\x84b\x87\xc0\xfa\xdbT[\\\xfa\x1dkU\x02\x99v\xecH\xca\x88\xdcq\x92\x08p\xe0\xa6\x84I\xc2\xedI\x18\xeb\xc5\x97)\x08\x0b\x8bbB\x0d \x10X\x94P\xbaN\xb4\x85\x9at\x0fz\xed 2\x0dI\xe6=\x12=\xa4 \xa6\x1f\x1b\x1c\x0e\xb3\x88\xfd\xa8\xc3;}\x86b\x8a\x9c\xe0q\xfe\xd3ji\xde\x86\xa7a\xb2#\" \xac\x17\x9f>1\x01\xbc\x82\x90\xb01\xe4A\x9b\xa3p1\xd6\xed\xddP\x82\xa7O\x12\x1a\xc7\x04\x13\x1d\xe8O\x97ux\xf7Q\xf4\xf9\xb0\xb9\xce\nF\xcf\xb2(\xfah\xdd\x84\xa9O'MDx\xcaL\xedK\x11$\xc8\xb5\x9ch\xe6&\x0d\xf9\x8b\xa6\xd0\x04\x001\x8c\xef\xc44\x9b\x9bSi\xa0\xdc\xe3rHJ\x16\x92P\xb0t\x00DM\xcb;rM\xe3\x82+\x94\xf6\x97\n*\x96\xe0\x9f\xed\xd8\x975u\x172$\x07\xaaf\x103\x92K \xdf<\xf9P\xb2L\xe7r\xd1c\x8bI)\x81\x98\xd6\xe5\x16^\xeb\x1fda>\n%\xc5\xe0\xd1\xb3b\x0b(\x9f\xfa\x96@\x08,\x912f,~\"\xa67\xdbR;\xaeE\xd1\x1d\x8e;\xac\xad\x94HX\xe5(\xfa\xb9\x12\x9f\x17\x1c4\x8a2Z\x03\x1f\xe4\xdd\x08'\x00T\xaa\xdb\xbf\xf6\x8b\x81\x84\x04\x0f\x94\xbd2J+\xff^!#o\x1b\x8e\x84\x9b\x94Y~4\xd8-\xd7\x83\xf2GW\x1f*\xf0!\xdf\xc3A\x95\x1a0&8\x80f\xe4{`\xbc\xbd\xf8\xe0W\xf6=\x92DP8\x92'\xff\x13= \xd6R\xa6 g\xa9}\x10\xf4iP>\x93\xca\x03#\xb9\xcb\xe5\xb94\xc3\xd2E\xd0BRY\xae\xc6^4e\xf3\x02\x9d\xfd\x82\xa7N8\xb8\x8fV,[B\x8b\x86\x15\xc4\xa8\xeeD#\x81X\x86\xf8]\xb2,\x19\xd6\xe8\xe2\xabLBsNC>\x17\x0d+\xa2\xedo\xcd\xea^x\xa8\xec\xa7\n\xa0\xf7\x0e\x95\x90\xfajC\xec.4\x0f\xc0Y\x11a\x89_{e\x01\xa6A2=r\x8e\xf0\xd8+\x00\x89\x05\xad\xb4\xd6\xee\xa7\x04\xa19PO\xbbA!!\x0b\n\xd7}\xb4Y\xcaP\x1a\x02Je\x84\x15\x97\xe7Gn\x9a\xb1%x\xfc\x8d1\x16\x14\xac/}Rg\x12H\xd8\x08\x9a\x11a\x0c\x8e\x01^3-\x8a\xa9 \x8b5\x06\n\xb6|\x8b\x01qS\xa7\xd0\xf0a\x07\x08WK{\x0c1al`I\xc0\x181\xd3\x0b\x99\xc6Q\xe9\xbe\xebf_yy\x05C\x19Z\x14)\xc4L3X\xb1]\x0bW6@DM\x99\x15T\xf8<.\x84\xabu\xebG\xceK\x8c\xec8\xd9Ds\xf4\xda\xd0\xb1\x03W\xe6\x91r\x85\xdd\\\xdf7Z\\\xd5\xcb\xff\xf2V\xd3\"I\x18\xa6\xa2\x8c\xf5S\xa1\xa7\xaed\xb5\x89>C\x8e\xa6\xc8U\x81j\x90\xdf\xc9e\x02\x9e\xc9\xc8\xd3D\x13\x05 \xae\x163\x19M\xc7tWcP\xef\xaf\x05\x86\x96\xf2\xd3\x896#3Q\xd7\x02\x9an\xe1\x89\xa9\x85\xb0J\\\xba\xa1\xc3\x05\x197\x9e#\xe7\xa3\xb1`\xd8\x80K\xeb\xeb\xa4 \xa9\xd7\x08lV\x036\x0b&\xd3\x1fT\x1d\x8e\x92 \xde~\xee\xdal.\x92\x9d\xbe\x16\xa1 <\x98\x98BP\n\xa3*\xb4!zRZ\xc4\xe4e\xd1\x99\xbb\xbe\xbe\xd9\xb7\x04T\xb1#\xa3C\xe9LH\x13\xb1\xac\x18\xc8\x16\xaa\x08W\xc5)\xdaD\x9b\x86\x16\xf7\x93p\xaeYU#\xc9\xca51{WJ\x80\x8e\xa44^\xc4f\x12\x19\xb3\xcc\xbc\x15Z\xb0\x11\xf6\xcc\xd1y6\x96\xd3\x91T2\x99d\xce4H=\xeaB\x84\x1e\xd2\x8a\xc9\x10\xac\x0f}\x9c&\xdd\x83\xea\xc2,aP\xc3\xa7v+:2\x16\xe6~\xf2\xc1*0\xbc\xb0\xa2\x88d\xa6\xc9\x93\xc2\xf5\xd6\x83d \x0c\xc2\x82\xf8\xe1\xcb!\"A+\x89r\x00\x90Hn\x0c\xa1\xc7\xe0sA\xe4\xc1\xc8\xda\x97U\x0d\x80\xfd\x02\x04\xf8\xa4b\xa0H\x93\xdbN6\xfe$.\xd0l\xc0};\xbd@\xa3\x11\xa1\xe2\x14iK\x7f\xc3 \\\xac\xd2\x82:v\x1e\x89QE\xc7\x00:\x1d\x08,|\xfd\xaaQ\xa0 Y0\x02|\xc7%\x18\xd6\x16\x19@\xed\x13\xb0 \xdc\x81\xe4qc\xe7\xd3\xd1dqh\xaf\xab\xe8\xab\xb9v\xdcC\xcdG\x07V\x86\x06\xb0\xa9\xb8\xaf-(\xd1\x03\x88m\x11\x85\x05\x921\x12\xbb\xae\xe2q89KF\x96\xd6\xc3\xa4\n\"2\xb1\xf2}Rr\x16z\xf3\x8e,j^\xa5\xc0q\xcb\\\x04\x85\xdd\x96#p\x19\x83\xbb+\xf5`f\x1dl\x9a\xb3\x13\x1c\xbd\x8f\xe2:k\x0b\xb4t\x965E\x84\x1aOaI\xc3\x0fJ\x16\xacP\x0d@ps\xadE\x99j1\xe44;6\x12\xf6\xf4/aH\xce.\xbc\xcf\xd3\xb0T\x00X\xa4p\x93L\x8b\xb8\x08\xc4L8\xa4\xbdF\xe7\x84\xdc\x9ai\xa8\x01\x0el\xed1\x96\x12\xb2Y\xd8\x8a8\xc9\x0d%\x8d\x16!/\xc1\xf9{\xad\xa8\x0e\xd2\xc5\xf1\xa0\xe9\x9c\x8b\xd9\xe5\x1d\xc6X\x9c\x80\xba\x07b\x88\x95\xbd\x85\x00\x15N\xc9\xc2\x04xp\xbb\xba\xe4\x06PW\xea\xbd\xdb\xed\xe8\xc4cI9\x18g\xb2*\xfe\xba\xbf\xee\x9d\x83\xb9\x9c%:\xd6\x1d\xbbL\xcb\x06\xdeu\x8a\x82CAO\xc2\x8c\xad\x99%\xac/\xc5\x93\xb4(Y\x08\xa2\xb3\x10^\xef?\xa0\xde\xe3\x1d\x81&I'\x88\xc8\x12uh[x\x14\x8b\xb4\x96Q\xf4$\xc7z\xd2\xb5\xc5\xbd\xf8\x01\x82 \xdf\xb3\x9e\x81\x82(=V\xd7\x80\x9f\xea\x0d\x02\xbem\xf0\xad\xc5\x04U)\x0b\xbb\xedl\xce\xa0\xce\x92\x18\xbe\xcci\x9c\x02\x18\x95d\xe3\xa6\x88\x99\xa8\xbd~f\xa6\xf9jG\x1b\xed\x01\xb5\x03\xd6R\x06{D\x80%>\xae\xa5\x90@\x94\x85\x946\x82\xa5\xa41\x82\x9c`\xc6\x1a!\xce ` \xc5\x1d\x86\xb6wY\xf3\xa7\x7f\x89\xd5\xe0\x81k/\x08a\x9d0A\x12\x86\x02\xab\xc2\xb9\x9f\xd4\x81\xb4\x0f\xcaYh\xb2\xaf\x97\xb5\xf2\x88d\xec\xe6x\x9a\x91k:f\x9a\x83\xff\xef\xa6\x1f\x92<\xd5\xd8\xd9WL4\x81`\x1d8IYMB\xc1Slc\xe4\xd6\xdf\xc8\xe0\x99-\xbbE\xd2\x82'\xce\xda\x8c\xc5:,\x1d\xffD\xac\xb0\x90\xe7\xd1\xd9\xf8\xc6\xa98\x184\xd3)~\xf7\xff\x042\x04\xb7j\x80\x9f\x96\xc7\xa0\x10i\xb6\xb7\x04\x0fB(L\xe3\xb5\x06\x08|\x0b\"a\xa9\x9a\xa6\xaf4,\x06\xa6b8\xa7\x94\xa5\xd4\x93\x17i 94\xa6\xe5\xd4\x11\x8c\xd2jW\xd1\x89\xb0\x1e\x0c\x02\xa96*\x90\xd0T\xf0\xa3\x1b\x86c4g\x8a\xcc\x93\xa2\xd7UM\xc9b\xb3R\xc7E\x00\xb2\xfe\xaa\x8b\xf2\x85\x1aC5\x91\xc6)j\xe4\xc8\xb4 \x91\xad1\x8d6pb\xc3\xeb\xdb\xc6\x8eH\xf7\xa7\xaaFx\xf2\x88\xf1\xb9\x01\xbf\x97\xaf\xab\xc4\xa3\x8f%4\xe2\xf2Q\xd9\xc4\x17C\x04\x89\xca\x88\xa7\x0e\xc5 \x1c$9\xd2:\xc5M>\xf2E\xd6\xdda\x03\x01\xdc\xc6\x02o\xab\x81\xcc\x9f^\xc2\x15\xd8<\x02\x19Iw\xde\x11\x00Ygq\x8f7s[\x86\x1f\xf0\x92\xf0 -y\xd01\xd8\xb95\x86\x19\xe4a\xc4\xe3M\x06K\x9a\xd7\x90\xe6RB\xc7Y\x80\x86\xf3Fq}\xb9\xe2\xe7\xb1\xf48\xef\x01\xc0\xb2*\xc8Nt\xe5\x90'.Yb\x14\x84\x94\x9b\xa4\xcd\xf0Z\x15\xcd\x1e\xfbv\xc5K\n(\xca]\x05&\xc9\x9c\x13\x1c\x8a\x19(\x0e\xa0\x1d\xd5\x99\xa5\xfd\x1e2\xaf:0\xd5\x0d\x80\xe4o\xa4\xce\x8f\xd1\x85\x1cPKiBH4U\xf0\xb9X,\x13\x8e\xa2\x8d[\x17\x88\xf0$\x0c\n0\xadmX\xb1\xe5\xbb\xd8\xb4\x8f\x82 \xf2\xa5f\xeb\x015\x0f\x15\xf0\x03\x040\xb1\xa0VR\x0d\xa98\xea%\xd9\xd1\xf1\xca\xde\xa7\xa7\x02Dt\xb0\xc3U\x8c\x91s`\xf4\x1d\xb7\x1b-BP\x8f\xc8\x0fz\xf4\x01P\x13\x94\x1ds\xeb\xb0\x03\xc1\x11\x12\x02\xa6v\x04I\xeb\xb68z-\xa5t1DiB\n\xd2\xdd\"\xcb\xb6\xdc\xc8YTJ \x83\xc4.\x9a?\xd40\xc77\xe0\x80jL\xa2\xc3N\x9e\xfa[2\xfft\xc8\xc2\xc4\xae\xcc\x8e\x18\x86\x8d\xe6\x00\x0b\xf9#\xfe6?E\xd7\xbb\x86\x94\x8c\xd7\x10\xa1\xae\x88:\xc9\x9e\xceY;\x83\xe7\xacA&q\x85\x13\xeaS\xd8IR\xc8)\xc9s\x05s\n9*x\xd2\xdf0Bj)m\x06\xec\xe1H\xa7A\xbe\xf6hy\xd0\x8fh\xf2Mm\xa4&4\xc5\x8a\x854\x80\x0b\x80\x87\xdc\xdag\xb8\x9fV\xe6&tY\xf3\xda\x1e\xa6\x02\xcfOCS0\xb3Y\xb2\xf4\x82d\x077Mv\x8d\x07N\xefj)w\xeb\xf7A\xc9(\xac\xe2o\x7f\x0d\x1f\"\xcd\xa2\xc9[\xa6\xd6\nE`\x9b\x94\xfe\x8a\xeb7ez\xb8\xc4\x8f\x86\x9d\xbb\xde-\xb7Q\xc0]\xa66\xdb+\x13Bca\xcd@^I\xc2:\xb2\xd2\xbb\xb4\xde\xfe\xbe\x1d=\x83\x02\x97\x9a\xad\x88sS\x9f\xe4\xcfn\x1dc\x08\x11\xc7\xf9\xd3 6\x1c\x0d\x82\xcd\xe7O\xe3\xa1B\x844\xbd\x88\x9f\xe7\xa0L\x1b\xa5\xa8\xc0\x07\x07Gp\xe3B\x89q/<\x95zA\xe3\xd3C\xc1\x01\xa5\xbb \x80\x05\xd4A~\xb9\x12\x16\xc9x\xd00\x0b6r\x17ih\xa3\xcdh\x1f\xa4I\xec\xd8\xb7O\x82\x03N,:\x0eo\xc7\xc1k\xec\xe7\xda\xf6\xc5/\xf3\xb8{H\xb0\x14\x15,\xdbz\xd0\x82g\xdaf\xc8\xbbz\x97\xaf\xd3\xce\x805\xfd\x90F\xf5\xb2\x14Tr\xc0n/\xe4t\x11``l\x86\xc1\x14\x06\x06\x99*\x08H6j\x1fT\x0f\xa1\x1etG\x04/x\xf8\xcb@P@(\x84\xc4I\xe8p\x0d\xd2e\xba!\xf9\xea`wv,:A\xec\x91\x9c\x0f\xb9\x0eN\xa3 4}09\x01z\xc7qC\x90\x17\xec\xe4$r\x00\xec\xfc\x02\x0eM`\x19Y\x86Q\x94\x92\xa0\xf8M\x7f\xe4\xe4\x95\xab\xb3\xf7\xc4(|\xe9B!\x0f\xed\x08>\x1d\xa2\xc1\xd8>\xabO pwj\x08 A\x02*@\x9b\x12\x90\x1f\xaa\x9fJ\xe4C[h&3\x8d\xfc\xebB \x1fQb\xfd\xcf\xa9\x108\x0b\x85:\xf1\x93%f~\x81v\x01/\x8bl\xe2S\xe4\xd0\xe8\xd20\xdd\xe8\xfe\x02\xd0\xf00a\x19\x93\xb7\xb6\"\x8eB\xe68(f \xfauGo\xc7\x9a\xc8\x0egy\xf1\xc5\xd7t\xa3_\xc3y~\xc0\xcd\x94\x8e\n\xc3%\xe4\x07\x85\xb0\xfb\x1dm\x90\x0e\x86L\n\xe8\xe0!I$\xe4Xt0\x83\xcf\x12\x80~\x16\xc0e\x8cP\x88z\xcb\xcd]\xa2U\xecg\x0d\x7f\xd0\x9d=_\xb1?\xf1\xba\x1b\xb5\xba.j#+`li\x91\xa1 \x1eB\x8a\x0e\xf1\xe2M5\x9b\x1f\xd2 \x0b\xba\xbf\x10\xc5\x91G\xd2p\x8c\x9e7\xaba\n\x86\xd6\x92\x1f\x8f%Y[\x18UG9\xe6\x99\xf2\xc6\xd3@\\\x05bD\xea\x1c\xd0Y\x1c\x85\x92{\x89\x9d{\xa4\xf0\x0eED0\xae\x97\n\xd6\x01$\x8d\xa0\x1bQ\xf8+FvC\xf0`\xdd\xa8\xec3\xb0\xfdQ\xa5 \x93\xee\xb1\x10E\\\xe0\xd0uC9\xcd\xe1\xc3![\x80$\x12\xeal\xef\xdf\xf5\x0b\x9a\xfa\x90\xea\x10\xf96\xdfD\xa8o\xd9Dg\xc0G\x88*+\x8dX!\xb8\x8d%#\x82C\x80q\x91\x0c?\xe9\xad\x0f8\x07ZU\x1aB)U@\x07\x08o\xa2\xcfpg\xde\xa9\xb6\x01Z\xd8q\x85\xa1\xa1\xc98\x8e\xca9\xf8\x9e\xc7|uc\xe1c\x08A\xd1\x9c\xb6\xad\xe9\xb0\x10\x95W;\xa9@\xe1\"\xa0\x11\x80\xd8\x19>P\x82\xd3\xef\xe5h_\x99\x9d\xc7\x109}.6\x80\x84\x90V/\xc7O:\xe03\x1b\xb4}\x8e\xa1\x13Z\x1cS\x0c\x1b\xb1\xb5\x9c{:\xd8\xda~\x92\xf3\xfe\x9c\xc5y\x0e\x1f\x8ak\xa6c\xee\x16\x88\xa4O6;O\xceB\xe1=\x97bV\xf1. R\xbfk\x8b\n\x01o\xf1\x0b\xa4\xff\x07^\xb1GV=\xe1\xd8 }\x11\xefoI\"+\x0d\xf4\n]w\x87\x81\xd7F\xaa\xc1z\xcf\xb7\xe4\xae\xf6`<\x93\xc9\xf5\xb230\x9d\xfb\x1f\x17h\xf7\x8c\xc53]\xeaR\x1ef\x7f\x05\xfa\x97\xbf8\x145\x04\x169s\xbc`K\x85\x06\x1e\x10M\x80\xa48\x03\xf1\xcb\nX\xbbUq\x88<\x89\x98\xa5\\\x98\x93\xc6ZO\xe0ss\xe8\xbfM\x92\xb7&\x03j\x1c&\xcf\x0d\xc4\xd6\x06\x02\xf7 .\xa7%\x9f\x0e\xa0\xd2P\xcaBL~^\xe4\xdf\x01\xff\xf9G\x88\xcb\x88\x913p\xe1D\x87\xac\x95:\xed\xb8\xd7\x1a\xa3Z\xbf\xa3\xc1\xb9\x04\xa8\xa9<\\\xf1\xab\xc7\xa0i\xaf\xa8\xdbW\xcc\x86\xa8\xc8\xc2\x10\"(\x94\x1c\x83:\xe1\xc5\xe2z\x8b\xa9\x96\x13X\x96~\xea\x81\xce0\x05P\x18G]8\x90\xef\x82\xbc\xaa\xac\x83\x8c\x88RQMN\x15T\x00\xa6qf\xddW\x03~!\xdd0\x94R%\xd5\x91\x9d0\xf0xvGFy/F\xf8-\x9b\xcfw\xfau\x82/\xf4\xee\x1f*\x7f\x01\xeb\x07+\x92\xc6 \\\xf5\xc28@\x886\xa2\xab\xc2\xfe\xa9\xb4\x8b\xbbc<\xb4\xe0\x0e\x1a\x16L\x02\x83;c\x8d[\x9a\x1e\xfb\xf7\x8a\x07\xdb\xd9\x07\xc2\xba\x0bnr \x9fQ\x15S'o\xa3Qu\x18\xf2T\xae{\x08q\xd2\x90\x90_\x9c\xcd\xbf\x8f\x83\x83S\x04d\xaa\xbbA\x04*\xc3\xb0:m\xf28Yuz2\xffPB\xab\x0d\xecHh`\x18l\xb4k\x92p\xe8\x13\xffLLh\ncEb6e\xdb\x8f\x00\xd2\x8b ?!\x84\x99\x10>|\x0b*=V\x8d\x01\xfc\xad\xbbK\xee@\x9e\xeb\x93rx\x910\xd3G`%\x08ryr[6\xea\x8aY3\x8c7\x8c\xc5\x0b\x87f\x17*\x97*\x18\x1bn\x95\xe0%9\x99\xdadf\xc3\xe81\xf31\xde\xa2\xda\x81^'\xcc\xfd]\x89\x9a\x96\x0dR\xcd\xdf\xe8q\x90\xdc\xd4.\xd8\xea\xf7\x00,\x9c\xf6\x95\x89\xd3^%\x84\xafl\x1a\xc2\xda\x11\xe2\x0d\xe3\xbde\x14\xd8\xd8#wW\x1e\xc2\xd1s\x12\xf356!\xd9=\xe2\xe5!q[\x04\xf6\xb0\xc4\xd8\x0c\xc3\x00%\xc8\xd4\xae\x18]\xf3\x8b5^:\x80\xbdm\xa85\xa9\x10\x10)\x01?\x11\x90V\x0bb|\x9au\xc07f\x93\x05\xba\x19\xecw\xb0\x9c\xe6\xc4\xf0,\x11:\xe7Y\x1ee\x0c\xe6\x86\x7fR\x07\x7f%\x94\n\xf2[\xc0\x9b\x8d\xee\x0d\x10\x1b\xc9o g\xe6F\xabA\x15z\xb5FP\xa5\x12\x9b\xf2\x1d\x9f\xc0\x10\x1d\xd4x\x9b\xb6\xee{\xcf\x16\x07\x07\xed\xf6d\x82x\xc3\xad\xd6w\x01\xc38\x8e\x98\x96\x08\xd9\x94{{\x03L> \xae\x82d\xac\x13\x812C\xe4\x00L\x91\xba\xa8\xe4L\x19\xde,\x9cL\xdc\xe8\x1e,\x84\xf2(\xe0mS\xec\xf8\x12\x9b\xc3\xd8\xe5\xe5$=\xd1|%\x9d\x15\x06\xd6\x9dlu\xe8& \xc4\x85\x94\x1a83\xe3\xda\nN\x0c\xa2X\xe5\x8ax\x0c\xeb\x0b\x04\\Vn\xf5\xcd\xef\x9eJ[)I\x9b\xea\x0ew\x8c\xc4/\xd1\xe9\xb9\xbb\xb2\xda\x0c\xb2\x7f\x18|\xa0G\xc5\xba\xd9\xd8Y\xd7\xc1\xf0\xf7DH\xb5\x98\xbd*\x9b\x12S\xfd\xaa\x8d\xee\xe8\xa4\xe6\x92\x1a\x1ap6\xae0\xd3c\x8fJ2\xe3@\xc5W\xb4%\xd1\xa6c\xef\xbc_\x1a^\xd3$\xd1\xe7#\x08*:G\xa7\xae\xe6\x186\x8e\xa1\xefn>\xcdD;\xfa\xf9\x02\xa5\x90~\xa4`9\xebhXB \xf1\x1dU\x8e\xabJ\x03B_\xd0\xb2\x88\x98\xf9\xcb\x88\xee%\xaa\xfd\x92\x01\xb4w\x17'\xb9$\xb3\xe8v|#T<\x0f6\x078\xe7\xaaKM\xb6\xcf\x91-\xd95U+\xbe\xb6\xa1'\xed\x06B\n\xcb\xc4\xaaN\x85\x91\xf8\x8ebJ\xec\xc3Ov'\xc8\xec|\x8b\x84+*M\x8c\xbck(\x0fd\x88\x0d}\x9b\x10C\xda\xcb\xb1@\xa0\xb3\xc1q\xb0\xb3\xb9\x04&\xf9aR%}\xb4\n\xcb!\xd6V\xd0\x83\x91s\x113w2\xa6\x8e\xd1a\xb22\xb2\xff\x8e\x17awH\xe6z\x10\xa1\x17/\x8d\x9dQ0\xf0\x02F\xa6 \xd9]~;\x03\x9e\xa5\xc3\xa4\x9d\x12\xcb\x15\xd6 ND\xf9P\nm\xfc\x98K3x\xde\x15\x8ake_\x99\xa3\x0d\xa0\xf1\xf3\xfeS\xaf!\x90\xa1V&=\xb2\x05\xb2\xaa\xb2\xbav\xe7\x19\x19_P\xc0\x8dL9\xd8\x83\x18Y\xa3\xa1i\xbf\n\xa7NU\xad\xd3_\xb6\xac\x11\xaf)\x96\x17\x83\x90J6\xdd\x7f9\x91f*\xca\xf0S \x10\xb1 \x11\x1d\x8f\x1e1\x007\xdaF|\xb8BR$\xc9\x15\xb7y,\x19\x0e\x04\xc6\xb1.\xbf\xc0\xd5&=uqs\xe1\x18\xf3\xa1OD\xc5\xf2B\x9b\x1f\xc8\xf4R\x84\x19=\xe7\xd9\xc9\xb3\x97e\xf8\xd8\xbd\xc9\x87\xe0\x1bB\xae\xac\x03\xe4\xac\xd6H\xad\xa1\xae\x13\x01\x88\n\x1d\xaa2lu\x03'\x9dh\x117^#\xffS\x85)\xa3Xi2..P\x00e\xa1/@F\xd5K\x13\xc9\x11\x91$\xe9](\x1a\xd8%\xe0|\x962\xc9\x1d\xf0\x13Y1\x10\x05pC\x9d\x07\xb18t\xc1\xf9I\xf8\xe311\x14N//+\\\xbb\x93p\xa5j\xd4\xc4\xef\xf4d\x80\x94\x18\xce\xe1\x18\x00W\xcam\x15\xe9\x9b\xc3I=\x04\xdf\xbd\x12\xb7\xd3\x08Y\x03\x93Zx\x1e\xa1\x01\xd4M\xd0\x89P\xfd8\xb2\x93\x011/\x0bJG\xab\xf5\xc4^U \x14,P\xc8d1O\xae\x14\xf3\x06^\xacy\xdfpq\x94\x13l\xbf\x81\x0e\xa32h\xdd\xd1$\xf8\x7fjv\xf1\xf8\x8b\xfe\xaa\x04\x1d\x01\xad\xcc\xf5\x9eI\x9a\xf6%\x87\x8a\xa8\xa7\xe1\xe8\xd4]V\xe6\x06\xce\x13\xd6\n.\x00'[+W\x12U8\x1b\xc1\xad[\x8e\xe5\x86\x01D\xea\x06\x92\xb3\xe8,\xdf\xbb\x05\xbe-\x0f=[\xc0\xe5\xd9\xc2\x06\x02\x0bO\n\nw\xff\x83\xa0\xbfE\xea)\xe53\xb1\xf8\xac\xe4\xf3\x0f\xbfJ&\x02\xa5d\xef\xd9\x82\xdd\xb6R\xc2\xa1\xac\x06\x97S\x96\\.\xb0 \x955J$I\x8d&\xf3\x91\x18\xddo\xaa\xb7\x1fH\xc8\xb3~\x9b l\x87\xbd\xcez>\x80\x1a\nUx\x08/\xf5H\xf1\xd0u;\x9a?Gt\xae{?\xe0\x0f\xb3;\xf3T\xa1\x8c\xaaH \xe4L\xfe|F\xfa8\xe1\x86\x03\xf0\xb2}\x88\xa1{\x0f\x18\xfa\x98\x1dp:\xdf2t\xec\xcd\x86a\xb7\xcb\xd1\xa7p6\xd1\xcf\xed\xd4\xfb\xb7\xb6\xf8\xe85Y\"L\xdaD\x93\x8c\xf9.\x8ar\xbc\xd8V\x0f\x93\xdf\x04\x91\x15\x14\x1a\xb2\x18\xdfS_\x0d\xba\xda\xcak\xfe\xcf]\xbbn&\xfaH\x8d\xb8\x0fz\xa7~\xa69\x91\xc3\xa6\n\xa6p\x0d\x15$\x1c\xa74\xd9\x82\x94\x8d'\xa2{\xba&\xa0\x01\xb8\xab\xff\xcbM\\\x9f\xce\xb0\xe9\xd1\x87\xa8\xae!\xecq\xaei\x08\x9d\xe0 \xcf\xc4(.h\x9a'\xcb\x0bB\xb1\x0bT\xad\xb2\x9f|\x0e\x1e\x9e{\x04\x06I\x846cL\x1c\xf2\xa1\x10.\xb9\x9e\x1e\xa3\x11\xeb\xb9\x8diI\xbe\xea\xab\xbf\\!\xe0\x1d;\x08\xa7\xe0g`1\xe2\x0c\x1d\xe1\xbe\x15\x95\x98j%\x10C \xb9o\x9d3*60\xf7\xb7E\x8c\x07\x98\xd8\x8e\x01\x9e]t\xe4\x89.\xd7-%0\x0dY\x1e\x89K\xc7_nft] \xb7\x17*VFC\x1f\xc6tJ\x92\xb0\xc4T\xd4\x12+\x16\xa4\\WZ\x908\xe1\xf2\xc4\xe2\xd7\x10g\x1bF\xd0\x04\xb2\xe0\x02\xd9^\n\xde\x9ef\x14\x9d\xb6 5\x9a\x12I=\xb6\xd7\xf9#6\xf6.@\xf52z\xd2\xc3;W\x9a`\xffB/\xc4\x99Q\x05\x05\xf8\x8a\x1ag\xed\xb0\xfc\x15h\x8a\x19jyJ\x9d\xd3\x19\xb0\x80N\xb2AX\xa43\xaa\xdd\x05,\xf5\xa4\x9b\x00\x0bK\xe46\xe8\x92\xeb6\x1b\x8f\xda\xb2\xd8M0\xaeT@\xa0\x8e\x85O{\xa1\xa3\x984k\x13j\x1f\xa3|\"\xacft\xd1\x9f\x94\xdb\x84U\xfc\x82\x18<\x08\x16-\xfc\x18\xdea\x86\x14\xae\xd5\x19\xe65b\x8f\xfa)\xed^R\xb1\xb08\x99\x84\xce\xc1\x9e:\x86\xa7il\x1e\x90\xbe\xad\xc0Ka\xc76@\xb5\xe6\x94\xc3!\xc0\xcd\x1a\xc3\x0f]\xa0buv\x0f\x1d\xce\x8f$ \x11\x87oU\xc7\xc2\x9c\x81~:.\x85\x10\x06\x14L\xfbt\x96\xe8\xeae\x97\xfc \xc7\x1b\x0f\x80\xa2J\xce\xbeP\nl$S\x13[z\x0e\x96\x8f~\x12Rq39\xe9\x92\xba\xf4\xb69\xebQ\x08\xef\x13\xcb/\x90m\"\x95%\xca\xa4\x89\xaf\x86\xbc7\x9f\x17\x03\x0e\x9a \xc3\xee\x1f5MKL\x9f\xe9\x91\xa7\"I\xdf\x8fG\x84 \xe8XT\xde\x8e\x1aXL\xbfF\xf0\xdd\xa7V\x0dj\x91p^\xa1/M\xc3g\xc1\xdb\xbb{\xb6\xb9\xbbw\xf4\n\xec*\xf8\xba\x80\x9e9\x0e\xff\xf0\x97\xcaO\xbe\xca\x88<\xcb\"a\x12\x1f\x0f\xf4\xc1\xfe\xf7A\xe1\xee\xef\x88q\xbf\xbb\xa2\x86.\x1fM\x7f\x97\x13\x002@m\xf6\xeb\x87p\xbf^\xda'\x93w\xdf\x95m\xf6\xc7k\x01xO8\x0b\xfc$[\xf3\xab&\x17\xc1\xfc|Y\x82Zy\xfd`2_|%\x11r\x97\x93/\xe5J?\xa1Q\xf9\xc3\x0eN\xcc\xb1l\x893\xc3\x9e\xce\xdfK\xa1\x14E$\x96w\xffv\x07\x13\x18C\xcb\x01h\x7f\xa3\xfb\x0ba@\xf7U\x801\xa9M\xf8\xbe%\x02\x160?1*\xa5\x0b\x96$G\xd3Z\xd3{!|\xc7\xca\xbf\x18\x11\x04\x10\x1a\xc0$\xc3\xdf\xdb\x95\x10\xc2-\x1b\xf2\xd9\xaaEv;\x90\x8b\xcd\x93:\xe4\xbd\x15\x8b\x9f\x1a\x06`Bl\xcf\xcb\xb8\xa0\xec\x8c\xa7\xc7\x07\xc9\xac\x9boQ\xdd0&\x8b\x02\x95\x04\xfb\xfe\xf1,\x86F?\xa1\xfd\xc6\xe4\x84^\x9ds,\x87c\x93\x99\xc1h\xcb\x95\xff$\xc3E\x13\xfccl0\xe5\x13\xbaw`\xfd\xe2\x8f\xba\xb9\xc5\x88\xa9@/\x80r\x07^\x16l\x988cT\xb73\x99\x9d\xdck@\x9b\xdc\xfaJ\xc2\xdd\x94\xb4uP\xd0\x18\x05&\xca\xaaN\xc9\xf3d\xf9Jj\x14T\x90K\xb8\xaai \xb7\xe9*u\xa7\xbb\xe9X\x96{t\x93j~\xbd\xc9\xa1}\xf9\xf1\x12\x0fi\\B\xc8K\x1den\xe2\x8b\xc8\xb5|N\xeb\xd6\xea\x0b\x9au\x9d\x92\xef#\xc3]@\x1fl\xf5CZ$iP\xe6a\xbd\xe3\xb8\xa9t04y20\xfc\x0ds\x11\xd8\xd6\xaa\xe2,Au\xc6!Q\x07\xd2\xd8B\xe4\xcf\x96\xf6\x96^\xec\x88@Vs\xc9\x91\x80\x82\\\xdeZ\xdfa\xe37\xa9\xec\xbe\x89\x04\xa9\x14\xb8\xe2\xd1\x88\xb3\xbb6-T\xefr\xb1\xc0\x17\xe4U\x98\x8f\x0b\xe0u\x18\x93\x8c~\xeb\xb01H\xc2J\xa8(<\xce\xb1\x8e\x82\xf2\xbd\x90\xd3\x1d\x0e\xb3bR\xd4\x96\xb8qi\x0b\xcf\xe9\xe6\xa2\x10\xacJ?\x1f\xede\xffG\x00\xc1\x0d\xa7*jV\xc4\xa7\x0c\"\xe1\xd8\xe3\x86:\x0eY);\x8f-F\xe5\x06\x05d\xf4\x17!\xf0H\xa3\xbb\xd9G~\xb4\x95\x1fu\xa6x cb\x8f6m\x95\x16\xbc\xf8)&;\xf10\x1d\x87\xcfdU?\x878\xc5X~\xef\x9f1\xd12\x8f\x9a\x17\xdb\xbc\xa8t\x80\x88I\x00\xd8x\xe85\x03\xc4\xc0{\x03(\xebz\x84\xea\n\xdc'\xbf\xfb\xff[\xa0\xc5\x83k\x8e\x08\xe8Z\xd0\x85\xd8\x12\xec\xe9\xcdi,\xf0\xc5b\x991\xcc\x87\x8b\xa2\xcd\xe1`\xba\xb1(\xf4\xaam\x8fH\xe1\x81N\xf0\xec\xfce\x89K\xa4\xb0\x10\xdf\xd4/\n[\xe0\xb4(\xf5\xf6#Q\xf4\x97G\x06d\xcau\x1a\xceT\xa9\xbd\x7f^\xf8m\xb3\xa2\xbf%\xf9\x86\x8c\xc5!(\x987K\x1cg\x03\xe9\x85P=\xe8\x13h\x0e\xf8\x1f\xcf\x95\xe1k\xc9\x90U+\x8c\xc2\xc6.[\xd2e\x05\xaf\x8b\xcf\xd0\x03\xbc\xb3C\xc1\x8f\x9e\x8f\xff\xe5\"GD\xff\xce\xa8\xa3\x9b<*<\xd6\xcf\xfe\xe9h\x0b\xab)\x18\xa4` A\x98U\x0c@O]h\x14\xfdl\xc5f2\x94\x85!H\x9e\xe7\xcfF#\x00QB\xc2\xe9=u\xc8\xbe9f\xb4h\x07\x80\xf3;\"R\x84\xa5\xda\x00\x92\x01K\xdc3-\x82(\x08G )\x05\xbc\x19P\xb1\xe1\xf8\xa1\xa8\x9e\xa6\xb2\x10T],7\xc1ec\xde\n\xeb\x1d F4hH\x0c\xd3s\xb3\x1473\xe1\x96\x9f\xa0\x12\xa1\xb2\x16\x0b\xe2\xdb`\xe0\xbaR\x96\xa1T\xedwf\xcd\xb3;6B\xf3>\xc5\x98\x0d9&\x15\x06\xc8\x1b\x05\xe2\xdb\x06\xd1\xda\xdc\x82\x02\x05\xce\x08?\x92\x97\xf7\xf8)\xc0\\\xa8\x8c\x80\x81<&O\xcc\x86\x99\x1c\xf05 \x11L\xc3Ju\xa5@Y\x9e\xdd\xdd,\x1d\x90\xeb\x83\xb2\xda\xbe\xdb\x04_w\x07\xc20\x98\x03^\xe917\xf1\xf0\x08\xf0\xf6\x11\xecp\xde\xbb\x87*>D\x948\xe3\x9f\x11\x98\xfc\xb0_)$U\xc5\xba\xf3\xca\x15R\xb4!j\x1aOF\xf4\xd6>{\x88\xd0\x1f\x92\x91\x0b\xbbt,\xaf-\x1c\x85bP\xb5,m`D\"/\x9fz\xf0A\xe2\x0d\xcd\x94\x02\xd8\xa5\xea\xdfQZG\xd5&U]\x90xej\x04x\xe6\x13\xe5Lwv\xf5~\x10\xb2\x9c=)@\xd8B\x1b\xaf\xd6\x086\xca?!;5\x143/ps@\x02t\x83OZS7\x10\x03\xa9\x94\xa7\xd8\x99\x14\xae\x92n\x9f\xd8lx\xe8\xfb\xee\xffZ?\x12\xe1\x83Z\xf9\x97j\x03\x0da\x0e\xb2\x96\x15{\xfd\xfb6\x97\xa5\xff\x19L4\x9b\x8a\xab1\x9f\x03\x7f\x0b2\xb9\xb4\xf9\x0e\xaf\x8bQ\x87i\x18\xdc\x19\xfd&\xd6\xa5l\x83\x88\xe1\xbd\xc5\xec]o=\x03\x1f\xa07\x1d\xc4\xc4\xbc of\xfc\xd0\x96\xfcr\x0bMEV@\x83\xe2\x0fH\xf5\x03\xa6\xe8\xf2\xfb/\xe8\xfda\x08D\xa5\xd9\xa6\xebH\x95\x83\xae\xaelK5)\xc2\x8cZ OE\xb4\x9c\x98\x1f\x84\x053\x10\xc1\xa6I\x01G\xa9'\xd0\xb3\x0f;\xeeD'\xb6zl(\x91\xa0\xf7\x9dE\x9f\xcf\xd1$\x9d\x8a.\xd9\x9c\xf0-W\x0c\x07R'\\w+)\xc2w3\xe6\xea\xba\xbe\xf9\xb8 @\xdb%R\xd4\x14)\xff.\xf2\x07~\x8a\x14\x059\x05;]\xf4\x14.\xc2\x9ag+)\xd8\x03%\xc8\x9d\xf6k\xd5\xce\xc0\xd2\x89\xb3\xa8^\xd2\x1f\xf6N\x80\x06W\xb7>b1z:\x1ds\x86\xa8oD\nK\x8d\xf6\xb2\xba\xc22w[|>9\xe2\xaevWMF\xe2\xafu\xde`\xb9\x1c\xeb\x13\xcdax\x87ch\xd5\xab\xf5U\xb7\x14\x81`*\xca\x86e\xfb]O\xa0V'6\xfd\x87\xc0\x03\x83x\xd4d\x1e?\xbcH]_r\xf5A\xbb\xa3+z\x11\xc0d\xadF\x9b\xafH \xc4\xca\x8b<\xa4\x1e\x01\x85\xc7\xb4\x1d\xa3\x04\xd5\x02\xc6\x04\x17kUsFz\xc0\xba\xf2\xcfaH\xd6\xc79\x07-\xb3\x9c\x90\x00\x98\x83gv\x82b\x07\x8b\x1f=\xd3\xebL/\x11\x9eE\xbb)\x10\xb0\xc4.\x98\xbdx9j\x13%B\xe3)\xa0$\x97\x8c\xe9A\xcbB\xa2\x8f\xe6\xec \x83\xdb\x1a\x9f\x01t b.b\xd2\x02A\x10E\xa8\x9eZ\x8dRb\xf6H(\x91\xa3\xf5J\xffya\xe3\x88\x1e\xd29Wj0\x05f\xa4\x1b\xdfF'\x9b\xb0X\xe0z\xbe\xc3\x0b\xef$DQ\xad6\xb4\xeb\x9eq\x83\xd8` o\xca\xd0 i\x14=\x81\xe1\xc1{#4\x14\xa4\x13\xa9FYH\xf9@\xd8J\xd03\x0d3i~\x91tY\xd0\xa2\xd9hk\x05H\x87P\xcf\xf1\xd7\x0f\x17\xf7\xfd17\xd3\xe0\xe0\x04\xa5\x86Y\xdcD\x97\"\xdcp\x97\xc4\xa6;'\xb31\x026\x80\xc6f\x97pu\x18\x02\x8b\x17\xa0\xf4\xbe\x04>\x11\xfeF\x9boD\xc5Qi\xa8n\xe1\xcc\x92\x8d-\xcf\xe7\x0c@P#\xe4\x9a\x7f\xab\x87 \x12\xa6h\x93j \xde\x82\x06\x88\xc5\x80f\xb4\xb6C\x0e\x18\x96 \x96\x81\x837\xc2\xb0\x01\x94\x17T5HVX\xc9p\xed\xf6\xc9\x02k\x12l\xc4\xad\x8c\xb3\xae]\x99\xdayX\x06r\xc6)?\xcd\xba\xd3BNJ\x9a\x0cB\x83\xf7\xf8\xe4\xbd#\xcb\x07\x9b9e\x18\x14\x94\x00&&\xbb_0\x95\xd3\x1f=\xae\x9a\x7f\x7fp\x15Z\x14\x8f\xc96\xa7\xaah\xa4\xd9)\x03\xf0\x0d\xcc\x97\x83a b\xc0\x8c\x15\xed=(p)\x87\xe2\xd9\xe5\xed\xac;\x8a.N\x10\x95,\x93\xc3W\xed^\x0c*\x03h\xd4\xba\x8aC\x97\xeem}E\x997\x00i\x10\xf5\xe0\x876\xc1\x82\x06\x02\xc3\xf7a\xcbI\xedv\xcd\xb2xp\x83*A\x7fc\x14#4\x82\xff\x17\xfd\xfb\x8c\xb3\xc7\x08\xa0N\xf6&\xf0`)\xae\xc4\x89\x88\xa3H\xa3We\x9b\x83y\x127jl\xa1\xef\x08\xb0\x00o\xdd\x13Eh_n3 \xad \x8bjp?\xaa4\xe8p2W\xc0E\x05\x1d'kT_\xe3\x0d&\xa3\xb0!\xc8\x96jVl\x98H\xed\xd3\xbb_k\xc9\x9a\xe1\xc8\xe2\xf6\xca\xb3\xf9\x0faY\xf9\x8c\xa0\xa1\x1b s\xce@\xe4[\x85\x04G\"\xca\xd3bY\xd5L\xdb\xdc\xabX\xa6\xaai\x8f\x0d\xd5C\x90\x98\x11q8\x01\xf1&\xfaz\x90\x90VaY{\xe8\xc6\x0e#I@\xb5\xa7\x7f\x1f\x9d\xad2\x98\x8em\x06\xf3!\xf4d\x01\x8c[1 \x85A\x10\xe0\xc6\xa2\x9a\x07\xffnK\xe8\xf0\xf2\xd5\x06\xc6e\xd7\x9d\xb2\xe5/>\x1d\x10\xdfd\x83\x02m\x86uX:x\xca\xb7\\\x84\xe2p\xf2N\x91\xfb\xfd\xa9\x1el\x9d+\x83H+c\xc7tS\xc7\xb6\x82\xe6\x1f\x14C\xc0\xb1[\xed\xe0~3\x8c\xcde\xc0}6\xb0 \x8d\\\xb3,\xce\xf1\xc9\x84\x98\xd7|\xa4Y\xf2\x04\x11\xdd\xa7\xe7\xf8\x98\xa7v]\xac'\xfb|\xbf\x9e\x9f\xeb\x08&\xed\x96\xecM\xf42\xb0 d\x10\xf5\xac\x00\x1bds\xe0x\x03-((76\x94\xa9a\x05\x03X\x9b\xbdm=\xd5\xee\xd3\x8a\xbf\xe3Q\x88\x97<$\x02\xaa\xaa\x00\x80\xfc\xf3Q\x05\x1e\xc2\x86\x98\x84\xba\\\x90\x02\x93\n\xd4\x0c\xaaqi\xe9H\xe9\x98\x87\xac\x8b\x89i\x06'i\xa4\x94$\x8f\"\xa3{S*V\x8fwF\x8b\x93/\xb0t<\xec\xca\xc1\xe1Q`\xca\x92Z\x16\xb8\x9a\x1e+\xf0pr)\x9b(\xb9.\x13j\xb5\xe9\xb8\xabI\xfck\x035\xf5 <\x04\xe4\xb4\x12\xca\x86\xb1\xcb\xae\xc9\xd6, k\x1bO\x91\x87\x9cDT\x88\xcaJ&^\x0e7\xba\xa3\x07\x87\xc4\xaaQ\x8d\xfe\x10\xa4\xcb\xcfv\xdfe\x10\n&\x9eZ\x90\xd8\x08\x92\x0d^4\xfa\xc6^\x06s\xb0\xf1D+`WH\xb5\x99\xae\x11\x81b\xec6\xd9\xc4\x05\x14\x05\xa9\x98 \x08\xb8\xae\xc8L\x9d\x98W{ZZ \xa6@\xb0\xe4mq\xe1\xfbv\xa6\xc9\xb7(\x04D\xc1\\+\xd4l\xe5\xe9\x14\xfb\x140*\xa5V\xa5\xdf\x87\xb0Vm\xd5\x1f\x8a\xa7\xe6h\xc6\x8f\xe6\xd8/S`|\xb3^\\<-\x99\x84\xa9\xc36\xeb\xb82\xa9N3\x9d\x82\"\x07\x0dT\x12o\x9f\xf3\x06\x04\x8clr\xe4\xc5e\xa0\x82\x12!\xf5\x04\xc5H2\x0b\x8b\x15p\x83A \xd6\x9b\xa8\xa0\x18\x87\x02\xde\xc3\xcf\x02{\x9b\xc8\xbc\xfe/\xa3\x1e\xf2\x9f\xd1\x00\xe7\x9cudU2*2\xf2\x10\"c\xab\xcc\"p\x85${\xa9\x80y\x81,\x0b\xe9\xa5\x8b\xf6\x11\x11\x1c&\\\xe0m\xbe&\xba`\x1c\xd0|x \xa6p\x85\x88C\xaa\xd2w#\xc2\xc9\xfbW\x909D\xadI\x07i\xf1\xd1\x96C\x88\x8f\x11\x9b\x02Ks\xef\x96\xe7\x87\x9d\x1dS\xb6\x07\x93\xe33\xef\x0c,\xb6\x0e\x91\x15\x96\xfeM\x9b\x92;\x1dj\xa8\xfeB\xeb\xa74\x9a\x9bP\x9b2\x02\xd9\xd9i\xb5\xee\xeff\xb6\xae\x00\xc9\xbf\xed\x17\xc1bA\xad]a\xa2id\xed\xc2\xf0\x10\x8a\xad\xa8\x0f\x86\"\xc4\xf2\xd7\x13i!\x07aQh\xd4CNO\xbd\xb1\x9e\x8a\xef\x82\x1a\xf5Y\xed\n\x93x\x06\x12F$\xc4\xf8g\x979\x16\x14\x9e\xa5\x10\x91Z`W\xab\x1f\xb0\x85VB\xe2g\xb8\xb1\xa0\xec\xda#j\\\xcb\x82\x97\xa8\x80e\xf9G\xf1\xfb\x1c\x0b[\x13\xb3.\x0f\x1d\xe0\xbe]\x8b\xaa0\x13\x14\xba~X{2\x9bD\xa9\x84?\x0b\x8a\xf8\"\xf3\x8a3\xc4B\x07\xe1j\x14,\xc0\x10K~\x0f\xc6\x06\x00b#\x840\x02\xac\xc9\x92L\x98\x01kc\xcd(6 \xb8\x0c\x02\n\xb1a\xfc\x04E\x1a7\xce\xbb\x81/\xd5\x8e\xaf%\x00\xad \xfc\xb1\x03\x9c\x0f\xb7\xef \xe0\xc9\xc4\xa1R\xeb^J\x14\xfb\x1b\xeb\xc5\x12\x04C\xcf\x8fZ+71X\xdb\x1a\x13\xb4\xd0UO,\xc1\x84\xf6\xe1\x14}\x0f#\x90-\x94\x90e\xd9\xa4\xa04\xf63\xc5\x82\xf0\xedt\xc3\x048\xa7\x99Z\x047\x08\x86\xcei\xe0\xac\xca<:i\xd1?Ft\x8bFk\x96\x7fC\x0cW'\x98\xea\x01f0\x01i\x02\x1b<\xe2Xdj\x97\xf9\x10\x8c\x940\xdb\x12W#i\x13\x8b\x0e\x8b\x9a\x96e\x08C\xcf\nzI7\x88\xce\x0eB\xb0\x03s\x18\xb7\xac\x98.K\x83\x0e \x12 *\x05\xeb\x8d\xddV\x91\xb0\x9d\xab\x12d\xff\x87\x9fD\x81lj\xf6@\xec\xab\xef%\n\xa9\xdc\x88\x9d\xe5\x9d\x0d\x15\xceZ\x88\xc4s\x18\xdd\xef\xae\x90sh\xcc\xb8%\x87^\xdf\n\xfd\xe8\xf8\xcd\xf7@\x188\x86\xf2\xa7\xa4\xf8\xce?\x0b\xa0N\xba8g\x17\xd4G\xf8gr\xa8X\xb0\x14\x17\x80S\x83\xbb\xa0\xfc\x06\xe4\x1b\x95\x0dAp\x0c\x91\x07\xb3\xba4\x87z*\xf6\xb94\xe1\x81\xdd\xe0\xa7,\xc3\xad\xb9\xc4t4G\xd9n\xd4\xe8\xf7\x91\xbc\x15\xf5dS\x0f\xe5\x13>f\xee\x94Q\x96C\xf2\x10\xcf\x1eWUZ{S\x08\xd9;N\x8f\x08x\xe5\xbd\xca}\xb0\xc7H&\xba\xbc*\x0b\xad\x009\xd7\xb8\xafq\x13\x8b\x9aU1 \xca\xf3\x0ca\xa0`(\x11\x7fM-a\xc8G}\xd5n\xb6\xcc\xbd\xe8\xa2\xda0 \x96\xbcp\xca\xd4\xc7mcn\xf1\x8e\x0d\xf2\xf0\x82\xc9\x98\xc0_\xfa\\\xb1\xfc\x17l\xbc\xde\xdb\xe0\xfe\xbb}\xce\x18\x1a \xc8\x00\x0b\xde9\xf7F\xe1\x1cv\x9eH\x7f\xc3\xbek\x83JZ\xfcNO \xe5\xb4m\x08Z\x81\xe1\xc1Q\x9e\xed\xd2\xa4 aS\xfb\xebf\xfa\x16\x81\n)\x11QC+2\x16\nd\x92\x98\xa1[\xaf\xfd\xbb \xcc\xef\x03\xc1\xf5H\"t*\xde\x0d\xc1c*b\xcf\xc6\xda\xa2\x01\xf7\xafq\xb0\xa8,\x05\xb5\x99\xf3\xe3\x13#\x01S\x98\x9f#\xa2\xe4u\x9b\x14\x0f'\xd2\xac\xf5:4\xa9\x1das\xa5\x03\xa9\xbeCDM\x90F\xa7\x13|\xc9\xb8m\xa9_\xc31L]\xf6\xe1Y\x98\x17\xca\\\xc0\xa7\xfd*\xa4X\x9c\x8a>t\xfa\x96\xaf\xb8\xcc\x16g\x8b\xa7\xd8D\x1c\x89\x9f\xa3\x8a\xf8\xe8\x0f\x04d@&[\xb0\x19)8\xc3\x18\xce;<\x9c{\xf3\xca8<\x11\x96\xc8+VG\\\xb0H\x98\xae\xa6\x1d^\x8d\x04\xafa\x97\x8ba\x90e\xdd-4\x94\xfas\xdaJ\xd4A \x1b\\\xe0\x0c\x90hM[\x82\\`\x14\xf0\x12\x93\xbc#\xbfpD5Z97g;\xb2\xf7BW\xe2m\xce\xe4\x89qTXX\x91%0\xb9\x00v\xba\x9e\xe3\x86\xf9&\xf9\xb7]E\x0b\xb9\x17\xdb4]\xfbF\x10\x9fIJ\xe4\xa4\xf9\x96\x9c\x84&\xddS\x8e_\x12\xa6\xee\x834\xc8R\x890\xa0\x02\xaf\xa5D\x05\xfc+\xcbme\xb9\x04\xd4\x05\xa8Y \x83g\xf7\xd0O\xf8\xf1+M{\x940\x06\x0f3\xcfv\x00'\xcd\x85f\x85\xc1\xc5t\xaf\xe1\x00\xe8\xa0:;\xf4\xd8\xb1\xca N\xf4\x07\xa6n\xe0\\\xc7\x94^\xdc,\x0e)1\xdel\xe3\xe1\x92aB\xef\x03ZZ\xda\x01\x84[\x95\xe0 \x04\xb8\x9d \xfbZS\xd2\xd2\xe4\xbcUYh\xdc\xdf\x86\xcf\xcaw\x7f\x80\xf5\x8b\x08\x9aS\xb8\\\xae/\xa4*?zQ\xd0\x8b\xff`\x90X4\xef\x1cg\xb9r\xed\xdb[\xa7\x08\x8aCW\xe6\xdbG\x16\xfb\x14.\xa7Y\x84\xec0Q|\xfbR\xd4\x83\x82E\x8d[w\xbe\xa6\xee\x84y\x83)\xb8\x10\xe1\xef\x91\x1a,\xd1\x88\xef$\xcbNK@c\x1d/b\n-#Z\xafI\x0d\x1b\xb9G$\xc6\x97\xaf\x99\x8btm\xe7\xcaH#\xea\xf0\x7f)X\xa3wP\x11ZAD\x7f|\xa2S\x0do\xfdf\x90\x8a\xf5T\xa4\x80\xddH\xda\xeb)\xb8\xce\xe4\xd3\xe7\xc7>\xaaM1\xa0b\x0d7\x1e\x03\xe1\x0e\xb0\x85\xc9\x86S\x8bu\xd0\xc3q\xd7\n\xf6\xb7\xf6jK4[s\xf0\x08\x84\x87\x10 \x1e\x95\x97\xd7x\x02L\x0c \x9b\xd6\x13\xbc\xc7\xa2\xa9\xeb]5\x0b\xfa!M!\x1fA\xbed\xc6\xa7N\xa0\xcb><\xab:\xc7\xbbZ(\xb08\x90\x86\xf8\x9d)e\x85\x0b\x84\xdf\x0d \xbb\xa5\x99\x86/\x99W\x15\xd8\xc8\xc0|\x0d\xfd\xb0b\xaa\x19\xd8\xe9\x88\xfa<\xe9\xf7\x9c\x83\xaeT?%\xc3 \x03\xb2:@\xb1\xe4\xd4,-\xe0\xf8\x80ecMP\xf08u\xa4m\xb0V\xd0g\x8d\x8c9\x1cH\xe9\xf66\xae\x1c\x12\xcb\x0f\xe7\x8b}\x0f\xbe=\x03\xb35\x00\x83\x81\x97Ab\xd2\xc4\x8e\xe6\xfd\xcf\xec\xb0\x81\xac\xce\x99\xc0V:\x92\x9d\x85_\xa0\x1cle\x1d\xc9\xb9\xdf\n\x11\xcf\xca\xee\x96\x95\x16v\x17\x0b\xfd`\xcd\x110\x8e\xe4!$`G\xc1\xe9A\"I;$\xdf^?\xfa\x81\x02\xae\x8a\x13\xed\x89Ke \x05O\xa2\x15 \xcd\xf7\xb3N\x0f(\xd5\xbd\xe7\xf6\x93Yy\xca5B\xe7\x1a\xa1w\xb8\xd0V\xb9%\x88ju;)\x16lF\xb5oa\xe5\xec\xcb\x15\x9b7\x8f\xf3x\xe9\xff\x92\xda\xb8\xd84-\x89\xc9%\xeb\x9d \x05\x86\xf0$\xcf\xd6\xb9/zsk\xc7\x98(sh>\xbb\xc1DD\xa9\xc5\x83\xc9t\xa5T\xc4\x117\xf6rur\x1a\xc0\x16\x9c\xb80\xc9\x1f\xd2\xa2\xa0`\x02\xdc\xb4h5\x0d\x025\x90\x8c\xa6\xc9\xe4\xb6\x00\x93S\xe1}\xb8\xd1\xdd\xc8\x15\x06\xff\xd24\x1bhrva\x12\xbc\x03\xe9l\xe9c!ZjB]\x81\xb9\x8e\xa6\xa9\x1a\xce\x7fx\xe2D\xaf\x18\xb6\xffb\x96Tx\x8fzYS\x82\x1f\xdf6_\xf6)\x83\xcao\xb0\xd4p\x08>\x98#\x8f@P\xa2S\xd3*\xfdb\xdcS\\q\x0b\xc6\x8bx\xf1YfQ><\"\xf3\x7f\xb7\xb2\xe3\xa2\x0dY\x1c6\x91\xc5\xf2I\x1fE\x0e\x00r_7\xf1\x88\xd2\xb0\x0cV\xd4H\xc3!\x00\xb3\xc5I\xe7r\x8cEL\xe7\x8e6\x19\x9e!N\xbb\x00\x12\xf6q\"'\x92\x1cd\xa0\x93\x01a\xfeqMv\xba\xc5\x0f\x8bA\x1f\x82%\xed\xf5\xba\xba\xbe \xf1v\xb3\xed\x15\xbd\x8e\x0bn\x1f\xf0.;\x1f\x9a\x1f\xebA/\xcf\x07\xe7\xb0\xf42\xca\xb2\x89\x9ca8D$\x17\xff\x03GWv\x85#\xcc\x8f\xfb\x0d9\xaek\xc5\xc5'\x06\x01\xfc\x89\xcbo\xd8\x9f\x9co\x80@\xe2\xfd\xcc (]gk\xed+}/\x03 (nq\x16\x87\xba\xecK(f\xa2\xcd\xd6\x0b\xdd\xc6\x9f\xd0\xb8\x9ep\x1d\xfc\xf8\xcc2\xd4\x1f\xc83Y\xb0\xe3\xdd\xe9w\x00\xb2pD\xfedG\xb4q2$\xcc\xc9}\x91K\x13\xd3\xafA\xad\"\xf6E&N\x82tg\x19'N\x07e\xfds\xd5\xf3\x1a!\xd0\xae\xf04q\xec\x9c\x17o\x14}\xec\xbf\x9d\xa5S\xb5\x05\xb5\xeb\x1e,o\xd5jr/s\x0c\x9cT\x0e\xfe\x04MT\x97&\xf6\xd0\x1b\xf0Qf\\12\xa1h'&ctN\xa6\xfa'T\xc5x7\xbc\x81]2\xfb ;G\xcd\x0e\x02 \xca\x85\xeb\xa2\xe3\x17|T\xaa\x01++:%/ \x86\xe8\xa6\xfb\x8a\xb3\xff1T\xc2\x0b\x01\x91\xc5\xfa\xcf\x1a\x93\x0c\x1a\xf3\xcb\x80\x9f<\xd4\xf1\xcc4\xc2\x0e\xd3\xd4\xf9\x8a\x0e\xc0\xcd\x94\xd7\xff\x93\xcb\x97 \xc9,0\x0f~\xe1\xf2\x9d!\xa1W\x8bO\xa9\x1d\xe0'\x89 \xe1\xcd:s\xf1u\x01\xc8\xc6\xca\xd2\xa6\xd9\x86\xf9\x8f\x03(\xb4^\xef\xae\x8e\x18\x0c\xb5\xa5\x9c\xc2)\x98\xf87\xe8\xd8\x00f\xc1\x80\xd1ml\xa5\xf2\xd2\xb9\xee1\xc5\xabt\x19\xdc\x1d\xd2Z\x83\x04\xe8\x08h\xc0\x0d\xcaL0\x0c\xa7\xa3\xb7\x96\x1a6\xd2X\"J\xd2\x82\xed\n\x8c\x884\xa79\xd8\xd1 \x9d\xd6\xa9B\xe9\x1d}\x83\xde\xd4\xad`\xe8`\x91\xa5\xae\xf0\x84\xd3\x92\x7f\xe7 #\xa6J\xde\xefn\xe9\xe4\xf4\xd1_\x91F\xad H|\x9a\xa1$O\xc8K\xce\xfa=\xa1\xc5\x93\x1fi\x191\xf7\xa1\xa67\x8c\x94o-\x7fH\xcbq\x1d\xa1\xaa\xfbp[\xc9\xab%%:\x10\x04\x88\xe4\x80\xc9\x88\x15\x10i3\x1d\xdb\xa0\xfa\x84G C\x97\x00LL\x894\x8aS\xd0:\x9edB\xf2j|\x89\x88pY\xd3\xf6S\xfeD\x90P\x1d>\xb6p\xd3v\x00\xde\x04\xb25KLe\xe8{t0\xae\xf2\x91y\xc7END$\xe0*\x9d;z\x1c\xbb5\x9a\x8aN\x92\x02\xe1BI\xf3\xd9gn\x8c\x80\x7f.N\xc9|\xd7\xb6\xe0\xd1n\xd0\x05\x8d\x94R\xc8aS\xa4Z\xd7\xc2JcH\xb2\x10 m\xcd\xd1X\xf8\x06\xdc\xca\xdf\x07e\x90\x12k;_\x0c6\xc8,y\x1e\x01\xca\xc2b\x94\x8d0#\xa6Z\x84\xb8A\x14\x0d\x17\x06e|w\x82\xd4\xccG\x0dU\xbd1l\xb8\xcbLD\xd87\xc3\x84V\xa3q\x92\xddt[\xadxu\xddE\x94QUL\x88\x01\xef\xf0PB\x9dlZSh\x96\x92.\xe1\xe91Q0U\xec\xd9\xb18R\x84\x06i\x8d\xfap;\xa6\xf1{\xf3\xf4H#\x96G\x03ON\x02!?\xeb\xa3\x05\xe8t>\xa9Q \x08|p\xcak\xa4\x90\xdb\xf3\xa8q!\xe7gT,\xf6\xd5j\xc7\xd02\x04\xc3\xc8\x16s\xc7\x8d4\xed\x88\x8at\x1b\x94j\xe4\x0e\xb7n\xc6\x9b/\x08I\xc9O\x98E\x02!\xcb\x8bnF\xf5\x9b4\x12\xa8\x86\xb7\x88M\x0f&\x1e\xd41\x84\x1b\x92\x97\xbe\x85x\xd3$\xa7ew+v\x99S\xf0\xcb\n\x0e\x0cbm\x05]e%8\x0c\xb2\xe4\x90\x06P\xcc\xc2\x11\n!\xfa\xef\xb3\x11\x90\x8cs\xc2\x11\xf3_0\x066\xa3\x1b\xf2)\xc2\x8fQ\xb42JB\x86\xea\xd8\xfd\x01\x0c\x84[t9\xae\x96\x83'\x94\xa7\xb3\xd4\x9c,\xa7\xa2\xcc\xf4[\xbdf\x00\xc3\x86\xd7\x92\xb6]\x98\x1e\xc2B\x8aB\x1f\xc3@\x9a\xa6\xeer&B\x84s|\x95Q\x9a\x0d\xb0\xa7\x99\xd7g\xa8\xedOC\x88\x9e1\x87\xdcJ D\xe7<\xcc\xcf\xe2U\xff\x87\xb2\xce\xbc\xd3\x11(o\xa9!\xb3\x81h\xa6\x90\xdcK\xbdH\xfc\xea 0q\x9b\x88\x92\xa7A\xd1V\x88\x07\xbc'p\xb4f\xccy\"Q\nO\x04\x85\xdb\x0c2\xc7\x06Z\xbb\xbe\x9fq\xc2\xe0\xbd\x02#d\"\x9b@bQ\xbb\x06,\xae\x93\xc2\x0bw)\xeeP\xcd\\\x1db`x\x1f\x8a\xdf\x00O\xfe)\xde\xa2\x0cd\xbc\x13MC\x80$[Ho\xa4\x13\x90\x18W\xde\xa6\xd1va4{\xe4\xc7\xb1`52\xed\x0f\xfd\xba\x87\x06\xb3\x1e5;\x82\x19\x85X\xb0\xffao\x00K\x86;\x986\x93%\xc1R(\xc0\x82\x05\x8c\xd3\xc6\xd1\x85x9\x8a8\x0c\xc02r\xe3D\x1ec\xf7\x10\xa5@\xd9\x88\x8c\xe6\xbe\xc9\x10\xa4\xeeF\xd7<\x86d\x0f\x16\x07(\xc8AN#F\x81I\xb7\x9e\x9bz\x1cm\x1dE\x04\xfe\x89\xbbF=\xa9\xb1\x85\xc6\x9a\xad\xe5\x95S\x82\x80f\n4\xca8\xa7<'\xb4\x84\xedj\x90\xea\x8e\xf4-\xaa\x98\xda'\x08\xc7\x98<\xd2Tb\xf12\xddv\x80E\xc0t\xb8\xbfq\xa1\xd23qODd_\xed\xd0{`/\x9c\x0fhh\xea\x82\xf6\xcc`\xc2\x929_\xfc1hAY|\x19/\xf9\xeb\x0b\xab\xde\xb7U\xea\x08-\xcd\x95\xba\xd0\xc4A\xde\x0f\x94\xd5o(\xf1\xcb\xea\"\x93$r\xd8\x86T\xcc\xd7PR;\x15\xa7\x05.\xb8-w>&LJ\xf8i\x10\x1aC`\x05A\xa3^\x1b\xb1\x97\xd3#\x89\x80\xc4X\x178\x97t\x97\xf6\xe2H?\x80\x14\x08d\xc1\xbfa\xc3\xc4\x96TST\xda\x03a\x1e\xa8H\x9f0@\xd2\xee\x8a\x17\xf0\xf3U)\x88\xa3\xe6\xef^\x1be}Jb7\x17%\xd7\xdc\x94%\x0e:\x9b\xd3\xc6\xbf@\x00\x97\xafM\x8e\x07+\xf1\xbb\x17y\x94sq\x8e\x00\xaa\xa1\xebL\xcc\xd2\xfd\xf8\xbf\xe1\x0b\xca\x12Y\xaa\x19\x1a0\x0f\x140\xc3\x94\xf7G\xfcD\xa1 \x16>\xc4\xa9\xeaAW\x0b\x11\x88\xb6\xf02\x8dI\xdb:\xc4\xd9F \x9e\xc8\x08\x02\xc7\x03\x9a3\xe3\x9f2\xca\xa0\xedq\x17\x80\xf7\xc0\x94:6S\x95\x97\x8e\xd1]K\xce\xcf\"\xa0\xa5\x08\xaeg[\xa6\x9d \xe5\xcf\x91H\x93\x1b\x1d\x1e\x98\xe2\x03B\xac5\xc8V\x06\x1cEq\xdbLJ\x8c\x95X{C\xbc\x88\xb9\xa7B\xbd\xc5\x03\xd9\xd2!\x08\xa5P\xabI\xe1\x90\x1dq9\xbb\xf8Llx\x96\xae\xca\xaa7\xd2\x1b>\xd6\xa4\x96\xdb]@\xd5!@9H\x03\x94!\xaa\xed\xe4\xc8p\xc0\x1e\xc9\x99\x15\xd5$ \xe2?\xde\xd5)\x9b\xab\x81\xdc\x8e\xa8\x05l\xb0\x06/\"\xb1\x94\xc0\xcc\x81\x96\xaf+\x93@`}}:\\\xf7\x95\xaf\xd0 8\x95zQgS\xa3\xbf\x18+\xf2\x92\xa4\xbf\xc1\x92C\x84\xa3}\x80\x1bR:\x9f\xf5H\xfeUF\x02\\\xa1X\xfe\x92g\xf6\xc0\x18/\xe2\x08\xeb\x80\x04AZ%\x11c\x1f1\x10\xd5wlET\x00\x05\x96\x0fwX\x0c\xa0\x08ZNh\xa5\xa0\x85\x08\xc4yf2D\xc6 \x80\xc3\xb8\x18\x89&v\xaeL\x93q\xee\x1e4\xc67\x95\xf1\xa7\xfb\xcaz\xfa\xf0\\\x90iJ\x11y\xc0\xe8J-k\xafN\xc43\xbd\xa0\xeb \xa3-\xbc\x05s\x91\xd1J\x175\x16\x89\x0f\x97\x1e)\xd9V0\x99N\x170\xddd\xda\\\xd3\x9bd0d-\xa9\xe3E\xda[mf\xa3\\\xa3Um\xc1x\x11\xb2\xd2\xd2C\xabR<(`\xaa\xd1\x95\xe6\x1d\x83p4^!\x06\x9dh\xd4Q\xe8\x0b\x00`\xa2\xf9\x81!l\x08\x93 ~\xc6\x99\xec:J\x87\xc9\xa0\xf1l\xfcW\xb1\xfe\x809\xcb\xb8\xccZXB\x14=\xeb\xc8l)`j\x9e\x1d\xaaeVJ\xb3\xe0U\x80\xb3\x02\x86G!\xaes\xd8\xe71\xd4?\xc6\xbc3\x84\xa8\xc3\x8a.\xb3\x1e}b\x1bIa\xd9\xea6\xe0\x03\xca\x95\x06\x16\x0d\x1e\x9ct?\xe8\xc0\x80\xdeS\x07xZJ'\xc3p\ni\xeb,\xa6\x12.\x88\x8f\xf1\xac\x12\x90\xd8R\x07\x07\x012T`5\x00\x98-R\nBxr\xe6WH\x03\xf6\x0cJP\xb0e#Bb\x89|\x93\xaf\x94-\xb1\xfe\x90\xa1\x90\xec\x8b[\xb2\x84\xa0\xc6\x1c\xe4P\xc2\xe2\xfd\x85\x1a\xa4\xa8Eh\x8b\xb1\xb3\xc2\x8b(5S\x9c\xa2\x1d\x95f\xd5r\xe4\x1c\xc3\x19/]\x7f\xcb\x1c\xb0\xd1I\xc6\x8a\x0d\xcc\x15\xd6d\x94\xdeE#\xfa\xa2O\xaeS\xfa3\x979\xd3\xbb]\xb8\x16\xba\xb3\x80e\x1e\x82\xbf\xdb\xae\xd5\xc9\xb9.9\x17_\x8cb\xeae\xa7\xe6\xbeM\x8c\x14\xb4\x819b\x1e\x13\x19#e\x8d\xa9(\x92\xa6\x11-\x88 0\x9d\xa7\xd2\xd7Ra\xb1\xe0\xc6\x1d\x849\xf9\xba\x96\x88\x06\"\x02\xfe\x89\xb1\xfe\xfd\xfdU,\xe1\xc2%\xfa~\xbeX\xe8\xdc\x80\x1f\xf6\x97\x94\xebz\x80\x15\xdb\xbd{'6[@\x84t[W%\xfd\xd1*\x0b.d'vR {\x94\xd2\xf0h\x1e\x8a\x04\xa6!\xdeAed\x92C\xaaE}\xbbx=E[\x0e\x01|\xefB$7J\xa1* B-\xe1\x00\x0c,=\x11k7\x94[_\xb6\xea-\xd0I\xf4\x96\x0c\xa2\x15\xab\x80\x92\x87J5e\xd6\xcc\xb6\xc4\x01\xb4\x13{\x0d\xc8\xed( \xb4\x86;\x10\x8d\x05\x14WMw\xa7`\xab\xb0\x02\x80\xcb~p\xdcA\xa0\xb0z\x15\x0e 8\x87\x02\xeef\xe6\x13))\xe2\x8c\xe2\xc2(\xde\xfc@ \xa9\x08\xc4\xaa\x07\xd9\x85\x85\xd9\x03<\xe1\xee\x85\xe4.a%N \xf2\xecn\x14\xe9@bz\xad\xc3\x19\x87\xc8\xd1\x1a\xc0\xb5\xbf>\x1a\x1a\xc0\x90\xeb\x18\x03\xf4%\x85\x87\x80\x05T\x07*?lgb\xbfd\xf6\x10\xc8<\x82\xc4\xb5\xe3\xfa\xc0w9Na\xac\xc5\x13\xbc8;<^*%\x9d\x9by\xd2:t\x11D\xa5\xd2\x95Z<\x1c@\x1b\x05\xfc\x890\xaa\xa8\xab\xe4\x82q4\xb1\xe4\xd0\xedl\\\x0d\x96\x1f\x15\x861\x86\x0e\xee\xc9\x1b\x9f\xd3\x00`/\x9e$\x12IJ \xd2\x93sN)\xbc;\x07:A;\x92)$\xd7\x95\n\xb0Ww\xa2\x12y%Kr\xdeIv\x0f\\b\xb6V\x07\x99\x06\xa3\\\x1cn\xadd{\xc0\xde\xf4\xc86\x15t\x10\xbb\x90v\x9d\xed\xd7/~\xa2\x00\xfc*O\xd6\xed\n\x117U\x16>\xa38\xfb\x17r\x82AC<\xba\x13j\xe9\x8aE\xe2\xa2-j\x0f\x1c\xe7\xd8\xe7\x89\xb7\xa8\xfcxs\xee)\x81\x8d\xccD\xa2\x9b\x961\xbc\xc3\x8c/\xcf\xcaq\x93p**\xcc\xb8\x18\xc0$\x02\xd9\x91\x8d\x13,\x0b\x16\xdb\xe1\x0d\x83\xb3B\x1a\xf5\xc8\xbcp\xc4\xfa\x0ek \x1bM\x17hp\x88K\xea7\x17\xc6\x15U\xe8\xa4\xc3]\xf0\xf8\xe1\x03h&\x18\x84-\x19\x13\x9e$\x03\x88\xe9\x8e\xbb\x81\xaf\x94\x93Y\xea\x90\x1b\xa3;\xe0q\xcb\xe96w\x95z\xdd\xf7\xd6W\xfb\xee\xcb\x84\xd6\xadA\xa6h\xb2\xecD\x7f\x9c\x91\x03^R\xf6\x03\xde\x1e\xc9\x01\"\xad\xc6s\x0f5\x00f\xfd\xfc\xeew\x0d\x88\xbf\xe4+\x10\xe7Q&\x12\x1f\x11\x92\x0e/9\xc8\x82\x96\x9c\xb8wN\x1eb\xc7\xeb\xe9\xfc\x90\x90\x19\xad\x0f\xe3\xfc\xb0\xd8z{\xe5\xd8\x1c\x95\xd3\xfeY\x17\xc5>\n]NE\xda\xc1\xb1c,\xdf\x9e#\x0cBF\xfd:0\xcd\xd8/-E\x18\x13\xc8\xbe\xc6\xc2\x8c\xc7\xd7\x83\xeb\x11F\\\xea\x8c\xf4\xe4I\xa7{t\xec\xe4A\xbbZ\x89C\x99O\x0e\x07R\xc3\x1buk\xa5\x0ci\xfa\x94\xf4)\x85ytkd\x9dN\xb8&\x16\x9bv\xa7\x15A\xb1\x99\x88\x0cP\x02{\xcd\xd6\xee\xf4\xcbP'\x9a\xf3\x92>\x02\xc8\xea\xe0x\x02\xe0\xc6\x86`.\xdc\x04\xe4%,;:\xd4\xbf\xd9:\x0f\x8e\xa9\x1a\xab\xad\xbf\xedaF\xf1\xa7o\x1aTQ\xab\x10}v#\xf4\xec\x9a\xd7\xa3\x02\x91\xf6\xdaQk\xe8\xc6'\xdds\xc4\xd4\xd3\xd6\x1f\x08\xd8\xf7\x12~\x85\x0f\xb5\xde\xcdz5h\x1fM\xc4Q\xca\x92\x06\xe1Y>C\x19\x85\xe8\x07\xca\x8d\x99\x00\x84\xe8\xbei\xb7\xcc\x02\x1d\x18U\xb1\xa0\xd3NF#\x11J\x180u\x8c\x05\xceC\xf0\xe4\xf08k\x93\x08!\nf\xab\xe9\xec\xa7v\x0c\xb9{\x7f\x1aE\xf1/\x1f\xcf\xeb\xe6IKIE\xcb>\x0c\xbap\xb7yd\x86\x13\xcce \n\xca\xbe\x12\x94=z\xf4\x86:@7\xd6J\xe0\xf7\xc4\x0e\xb3\xcc|\xc6\xc65g\x07\x0f8\xc0\xeex\x0c\xc53\xe7O\xb1\x8c\x1d\xaa\xfe\x80\xc4\x10\xdc\xdc\x07\n\xfe3\x1f\x80H1\x8b\xf3\xb1\xd8\x84F.\xa0y\xb4fz\xb4\xecW\x06IM\x1b\x0b\xf1\xd9\x19\x83\x18\x11\xc6j[\x81\x17.w\xe6%\x08\x84i?\x01\xd2\x86U\x12\xc2\xe8\xa9f|}@+\x04[8\x95k7Cx\xa4\x98S\x90\x85\xedEO\x02\x12\xde\xafp\xa0$\xe4\x17\x97\xfc\xe1\xe7\xbeQ\xe6\xbb+\x99\x19\xca\x03:\xb8<\xe1]\x81\xb6\x01\xb8K\xe23\x8f\x8bT-y\xb2\xc2\xcd\x16\x08[N\xd1\xd6z\xb4\xb5\x84;y\xb3\x8a\xa4-HZ\xfe\xaaY^\x15\xa1\xd4.\xa5M\x00*\x08\xd4'h8\xd2\xedA\x85\x04.\xb0N\xef2\x16r\x89\x9cLB\x9c\x0b7:Or\x8f\x92\xa9}\x91\x12C\x89S\xcb\x9aS\x199\xe4\x01Jq#\xec\xa3\x12WI}*8\xcbD!\x1b\x88\xb8# \x11\x14g#Y\x8f>\x138\x18`\x95\n\xec\x15\xd0\x92\xc2\xf1\x03\x0c?a\x85\x812\x12H,\x1f^\xf1\xe3\xc4'\x83\x8f\xef?\xb8\xff\x03\x90\x0e^\xb8\x88\xe6\x03\xa7n\x83h\xe3O\xc6\x92\xad\x07\x1a\xbfi<\xd1\x19\xaa\xe6\xddY\x0fa2\xc9+\x1e\x99\xfc\xcc6a\xb0F\xb1\xe2a<\xcc!\x84\xdb0\xac\x892\xbd]\x81c:\xefe\xbcK\xa4\xac\x1cX\x98X\x98[Ug\xe9O\x12\xafu\x175i\xd4yPcV\xd9T\xba\x9e5\x1fR\x01I\xfa\x9fA6\xf2O\xd4\xb8i\x0d\xa4\xfdC\x04\x8e\\\x87\xf1\x1e\x85\x97\xe3Q\x0fZ\x13\x8dM\x84D\xc4\xc6\x83\xd3\xda\x01\x90\xcfB!X\x96\xc4:\xf4\xd0\xe3\x08\x1c\\!\xc7\x14\x18^\xc1\x85\"\x14{\xa1E \x14Va\x07x$P\x1d \x17\x18\\$\x02\x0c\xb3DBBT\xde\xd3Ft\xe8\x9f~\x99\xc3{O\x87\x1e\x04\x00\xbc\x0dw\x00\xef\xf8\x9e5a#\xf8\x07`\x90\xab=\x04\x16\x00\x11g\x81\x12\x80\x11\xd0\x81\x13\xb0\x01Y\xfd\x192>\x1d\x87\xb1MG\xaf-G\xadk\x8f\xc3\xa8\xaa\xdb1T\xbeb\xa6\xfc\x85L\x18\n\xb9`*\xd9\x80\xabV\x02\xacX\n\xad\xde*\xa5x\xaae\xc2\xa7\xd6\x8a\x9dZ*c`\xaaV\xc1S\xd5b\xa5\xba\xc5JU\x8a\x92\xaa\x15\x1d\xd0*6\xa0TK@\xa8zqP\xc4\xe2\xb6\xc9\xc5h\x93\x8a\xc7g\x15\x86\xcc*\xdf\x94U\xa7(\xaa\xf6QU4\x82\xa79\x05L\x92\n\xadc\x15M\xc6*\x90\x8cT\xbb\x18\xa9R!R,B\xa3\xc8\x85E\xb0\x8a\x88\xa0\x15\x0f\xbe*C|Tz\xf8\xf4p\xf0\xf4F\xe8\xf4@\xe8\xf44\xe8\xf4*\xe0\xf4\x10\xe0\xf7\xf5\xb1\xee\x05\xb1\xed\x85\xb0\x96\x86\xd8\xac\xe1\xb1X\xf3b\xb0\x06\x80\x1cL\x80.\x99\x00T2\x00y`\x00\xae\xc0\x01Up\x02b\xe0\x03\xe5\xc0\x05\xeb\x00\n\x15\x00\x10\xaa\x00\x1bT\x00,\xa0\x00%@\x05\x1a`\x07\xe4\xc0\x0b\xe8\x80\x15\x90\x00#\xa0\x00?@\x00t\x80\x00\xa4\xf8\x19GL\x88\xeb\xc5\x9e\x00S\xc0)\xf6\x01\x9e\xc3\xbf\xa0z\x93\xfft\x07\xcf\xb2Fy\x15\xd7\x8e\x00 \x1a\x0014\x00Lh\x00\x8c\xd0\x00\xe1\x80\x01\x83\x00\x01f\x00\x7f\x99\x00\xb0\xc8\x05e\xc0(.\x01)p\x08K\x80@\\\x01\xe2\xe0\x0c\x97\x00X\xb8\x02e@\x05\x15\x00\x08T\x0fb\xa0v\x95\x03h\x98\x1aD\xc0\xc5&\x05\xf90-I\x81bD\x02\x89\x10 d@\x1f\x11\x00ZD\x011\x10\x03\xa4@\x0c\x91\x00\x18D\xe0\x04y\xc0\xb8\xf3\x80\xd1\xa7\x00CN|\x0d9\xdc4\xe6\xd8\xd3\x9a#Nc\x0bl\xc2\x16\x05\xc0\xb0;\x05\x81\xb8,\x0d\x81`c\x8b\x03\x04X\x16\xe2\xc0\xb3\x16\x05@\x90(\x84\x812$\x030\x90\x0c\"@- \x00\x98$\x01\xe8\x90\x06B@\x16\x89\x00<$\x00\xd0\x90\x01\xc1\xc0\xf8\x0e\x078p7C\x81\xa6\x1c\x0c\x80\xe0b\x05\x02\xe8(\x16\x81@\xa5\n\x05\x18P\x05A@\x13\x85\x00F\x0c\x00\xb80\x02\x00\xc0\xf5\x06\x00t\x89\xfc\x01\x9c\xde\x04\x1d\x8b\xe4G\x16\xad\xe9\xd4OR\x97\x89\xe9\xc4\xb2\xe2I\xef\x1eT\xf1yS\x8d\xcdMW52\\T\xc6oR\xe5\xa5KV\x950\xc8\x8e\xac\x04\xe0\xbb\x1a\x82\x8c(\n-\xa0$\xb2\x80\x92\x9a\x01\x80\x94\x0d\xa4\x02!6\xa6\x84\xa2w\x88\xeaH\xa2\xa9\x0e\x86\xa3\xf9\xfa\x8fG\x12\xf9\xad\xa0\x11O r~\x07\x07\xe0e~\x06/\xe0]\xfe\x05\xb7\xe0V~\x05/\xe0P~\x057\xa0Sz\x04\xef\xa0K\xfa\x04\x97\xa0Fv\x04\x17`;\xf6\x03\xaf`9v\x05\xd1#\nJ\xa4\x1a\xdc\x17\xa7B\xcdN\x82,\x90\xe4\xd7\xce\x1f\xc5\xd3\xad\xb2'\xb0\x00\x00\x01\x03\x01`\x00\x00\x15\xa1'\xe2\x8f\x10\x82`\x04\\LT\xfe\xf0\xd9\x02A\x18p\x12Bs\x81)r\x85!\xd5\n\xe2(\n\x03\xd2\x04i\x82`PK\x07\x08X\xc7\xb1\x9c\x9fN\x00\x00\x9fN\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00fonts/glyphicons-halflings-regular.svg\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n PK\x07\x08|\xee\xc6\xc9\xc2\xa8\x01\x00\xc2\xa8\x01\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00fonts/glyphicons-halflings-regular.ttf\x00\x01\x00\x00\x00\x0f\x00\x80\x00\x03\x00pFFTMm*\x97\xdc\x00\x00\x00\xfc\x00\x00\x00\x1cGDEF\x01D\x00\x04\x00\x00\x01\x18\x00\x00\x00 OS/2g\xb9k\x89\x00\x00\x018\x00\x00\x00`cmap\xda\xad\xe3\x81\x00\x00\x01\x98\x00\x00\x06rcvt \x00(\x02\xf8\x00\x00\x08\x0c\x00\x00\x00\x04gasp\xff\xff\x00\x03\x00\x00\x08\x10\x00\x00\x00\x08glyf}]\xc2o\x00\x00\x08\x18\x00\x00\x94\xa4head\x05M/\xd8\x00\x00\x9c\xbc\x00\x00\x006hhea\nD\x04\x11\x00\x00\x9c\xf4\x00\x00\x00$hmtx\xd2\xc7 `\x00\x00\x9d\x18\x00\x00\x03tlocao\xfb\x95\xce\x00\x00\xa0\x8c\x00\x00\x020maxp\x01j\x00\xd8\x00\x00\xa2\xbc\x00\x00\x00 name\xb3,\xa0\x9b\x00\x00\xa2\xdc\x00\x00\x03\xa2post\xba\xa3\xe55\x00\x00\xa6\x80\x00\x00\n\xd1webf\xc3\x18TP\x00\x00\xb1T\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x00\xcc=\xa2\xcf\x00\x00\x00\x00\xd0v\x81u\x00\x00\x00\x00\xd0vs\x97\x00\x01\x00\x00\x00\x0e\x00\x00\x00\x18\x00\x00\x00\x00\x00\x02\x00\x01\x00\x01\x01\x16\x00\x01\x00\x04\x00\x00\x00\x02\x00\x00\x00\x03\x04\x8b\x01\x90\x00\x05\x00\x04\x03\x0c\x02\xd0\x00\x00\x00Z\x03\x0c\x02\xd0\x00\x00\x01\xa4\x002\x02\xb8\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00UKWN\x00@\x00 \xff\xff\x03\xc0\xff\x10\x00\x00\x05\x14\x00{\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x01\x00\x00\x00\x05\x00\x00\x00\x03\x00\x00\x00,\x00\x00\x00\n\x00\x00\x01\xdc\x00\x01\x00\x00\x00\x00\x04h\x00\x03\x00\x01\x00\x00\x00,\x00\x03\x00\n\x00\x00\x01\xdc\x00\x04\x01\xb0\x00\x00\x00h\x00@\x00\x05\x00(\x00 \x00+\x00\xa0\x00\xa5 \n / _ \xac \xbd\"\x12#\x1b%\xfc&\x01&\xfa' '\x0f\xe0\x03\xe0 \xe0\x19\xe0)\xe09\xe0I\xe0Y\xe0`\xe0i\xe0y\xe0\x89\xe0\x97\xe1 \xe1\x19\xe1)\xe19\xe1F\xe1I\xe1Y\xe1i\xe1y\xe1\x89\xe1\x95\xe1\x99\xe2\x06\xe2 \xe2\x16\xe2\x19\xe2!\xe2'\xe29\xe2I\xe2Y\xe2`\xf8\xff\xff\xff\x00\x00\x00 \x00*\x00\xa0\x00\xa5 \x00 / _ \xac \xbd\"\x12#\x1b%\xfc&\x01&\xfa' '\x0f\xe0\x01\xe0\x05\xe0\x10\xe0 \xe00\xe0@\xe0P\xe0`\xe0b\xe0p\xe0\x80\xe0\x90\xe1\x01\xe1\x10\xe1 \xe10\xe1@\xe1H\xe1P\xe1`\xe1p\xe1\x80\xe1\x90\xe1\x97\xe2\x00\xe2 \xe2\x10\xe2\x18\xe2!\xe2#\xe20\xe2@\xe2P\xe2`\xf8\xff\xff\xff\xff\xe3\xff\xda\xfff\xffb\xe0\x08\xdf\xe4\xdf\xb5\xdfi\xdfY\xde\x05\xdc\xfd\xda\x1d\xda\x19\xd9!\xd9\x13\xd9\x0e \x1d \x1c \x16 \x10 \n \x04\x1f\xfe\x1f\xf8\x1f\xf7\x1f\xf1\x1f\xeb\x1f\xe5\x1f|\x1fv\x1fp\x1fj\x1fd\x1fc\x1f]\x1fW\x1fQ\x1fK\x1fE\x1fD\x1e\xde\x1e\xdc\x1e\xd6\x1e\xd5\x1e\xce\x1e\xcd\x1e\xc5\x1e\xbf\x1e\xb9\x1e\xb3\x08\x15\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x02\x8c\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00 \x00\x00\x00 \x00\x00\x00\x03\x00\x00\x00*\x00\x00\x00+\x00\x00\x00\x04\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x00\x00\x06\x00\x00\x00\xa5\x00\x00\x00\xa5\x00\x00\x00\x07\x00\x00 \x00\x00\x00 \n\x00\x00\x00\x08\x00\x00 /\x00\x00 /\x00\x00\x00\x13\x00\x00 _\x00\x00 _\x00\x00\x00\x14\x00\x00 \xac\x00\x00 \xac\x00\x00\x00\x15\x00\x00 \xbd\x00\x00 \xbd\x00\x00\x00\x16\x00\x00\"\x12\x00\x00\"\x12\x00\x00\x00\x17\x00\x00#\x1b\x00\x00#\x1b\x00\x00\x00\x18\x00\x00%\xfc\x00\x00%\xfc\x00\x00\x00\x19\x00\x00&\x01\x00\x00&\x01\x00\x00\x00\x1a\x00\x00&\xfa\x00\x00&\xfa\x00\x00\x00\x1b\x00\x00' \x00\x00' \x00\x00\x00\x1c\x00\x00'\x0f\x00\x00'\x0f\x00\x00\x00\x1d\x00\x00\xe0\x01\x00\x00\xe0\x03\x00\x00\x00\x1e\x00\x00\xe0\x05\x00\x00\xe0 \x00\x00\x00!\x00\x00\xe0\x10\x00\x00\xe0\x19\x00\x00\x00&\x00\x00\xe0 \x00\x00\xe0)\x00\x00\x000\x00\x00\xe00\x00\x00\xe09\x00\x00\x00:\x00\x00\xe0@\x00\x00\xe0I\x00\x00\x00D\x00\x00\xe0P\x00\x00\xe0Y\x00\x00\x00N\x00\x00\xe0`\x00\x00\xe0`\x00\x00\x00X\x00\x00\xe0b\x00\x00\xe0i\x00\x00\x00Y\x00\x00\xe0p\x00\x00\xe0y\x00\x00\x00a\x00\x00\xe0\x80\x00\x00\xe0\x89\x00\x00\x00k\x00\x00\xe0\x90\x00\x00\xe0\x97\x00\x00\x00u\x00\x00\xe1\x01\x00\x00\xe1 \x00\x00\x00}\x00\x00\xe1\x10\x00\x00\xe1\x19\x00\x00\x00\x86\x00\x00\xe1 \x00\x00\xe1)\x00\x00\x00\x90\x00\x00\xe10\x00\x00\xe19\x00\x00\x00\x9a\x00\x00\xe1@\x00\x00\xe1F\x00\x00\x00\xa4\x00\x00\xe1H\x00\x00\xe1I\x00\x00\x00\xab\x00\x00\xe1P\x00\x00\xe1Y\x00\x00\x00\xad\x00\x00\xe1`\x00\x00\xe1i\x00\x00\x00\xb7\x00\x00\xe1p\x00\x00\xe1y\x00\x00\x00\xc1\x00\x00\xe1\x80\x00\x00\xe1\x89\x00\x00\x00\xcb\x00\x00\xe1\x90\x00\x00\xe1\x95\x00\x00\x00\xd5\x00\x00\xe1\x97\x00\x00\xe1\x99\x00\x00\x00\xdb\x00\x00\xe2\x00\x00\x00\xe2\x06\x00\x00\x00\xde\x00\x00\xe2 \x00\x00\xe2 \x00\x00\x00\xe5\x00\x00\xe2\x10\x00\x00\xe2\x16\x00\x00\x00\xe6\x00\x00\xe2\x18\x00\x00\xe2\x19\x00\x00\x00\xed\x00\x00\xe2!\x00\x00\xe2!\x00\x00\x00\xef\x00\x00\xe2#\x00\x00\xe2'\x00\x00\x00\xf0\x00\x00\xe20\x00\x00\xe29\x00\x00\x00\xf5\x00\x00\xe2@\x00\x00\xe2I\x00\x00\x00\xff\x00\x00\xe2P\x00\x00\xe2Y\x00\x00\x01 \x00\x00\xe2`\x00\x00\xe2`\x00\x00\x01\x13\x00\x00\xf8\xff\x00\x00\xf8\xff\x00\x00\x01\x14\x00\x01\xf5\x11\x00\x01\xf5\x11\x00\x00\x01\x15\x00\x01\xf6\xaa\x00\x01\xf6\xaa\x00\x00\x01\x16\x00\x06\x02\n\x00\x00\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x02\xf8\x00\x00\x00\x01\xff\xff\x00\x02\x00\x02\x00(\x00\x00\x01h\x03 \x00\x03\x00\x07\x00.\xb1\x01\x00/<\xb2\x07\x04\x00\xed2\xb1\x06\x05\xdc<\xb2\x03\x02\x00\xed2\x00\xb1\x03\x00/<\xb2\x05\x04\x00\xed2\xb2\x07\x06\x01\xfc<\xb2\x01\x02\x00\xed23\x11!\x11%3\x11#(\x01@\xfe\xe8\xf0\xf0\x03 \xfc\xe0(\x02\xd0\x00\x01\x00d\x00d\x04L\x04L\x00[\x00\x00\x012\x16\x1f\x01\x1e\x01\x1d\x017>\x01\x1f\x01\x16\x06\x0f\x0132\x16\x17\x16\x15\x14\x06\x0f\x01\x0e\x01+\x01\x17\x1e\x01\x0f\x01\x06&/\x01\x15\x14\x06\x07\x06#\"&/\x01.\x01=\x01\x07\x0e\x01/\x01&6?\x01#\"&'&546?\x01>\x01;\x01'.\x01?\x016\x16\x1f\x0154676\x02X\x0f&\x0b\x0b\n\x0f\x9e\x07\x16\x08j\x07\x02\x07\x9e\xe0\n\x11\x02\x06\x03\x02\x01\x02\x11\n\xe0\x9e\x07\x02\x07j\x08\x16\x07\x9e\x0f\n)\"\x0f&\x0b\x0b\n\x0f\x9e\x07\x16\x08j\x07\x02\x07\x9e\xe0\n\x11\x02\x06\x03\x02\x01\x02\x11\n\xe0\x9e\x07\x02\x07j\x08\x16\x07\x9e\x0f\n)\x04L\x03\x02\x01\x02\x11\n\xe0\x9e\x07\x02\x07j\x08\x16\x07\x9e\x0f\n)\"\x0f&\x0b\x0b\n\x0f\x9e\x07\x16\x08j\x07\x02\x07\x9e\xe0\n\x11\x02\x06\x03\x02\x01\x02\x11\n\xe0\x9e\x07\x02\x07j\x08\x16\x07\x9e\x0f\n)\"\x0f&\x0b\x0b\n\x0f\x9e\x07\x16\x08j\x07\x02\x07\x9e\xe0\n\x11\x02\x06\x00\x00\x00\x00\x01\x00\x00\x00\x00\x04L\x04L\x00#\x00\x00\x0132\x16\x15\x11!2\x16\x1d\x01\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!\x1146\x01\xc2\xc8\x15\x1d\x01^\x15\x1d\x1d\x15\xfe\xa2\x1d\x15\xc8\x15\x1d\xfe\xa2\x15\x1d\x1d\x15\x01^\x1d\x04L\x1d\x15\xfe\xa2\x1d\x15\xc8\x15\x1d\xfe\xa2\x15\x1d\x1d\x15\x01^\x1d\x15\xc8\x15\x1d\x01^\x15\x1d\x00\x00\x00\x00\x01\x00p\x00\x00\x04@\x04L\x00E\x00\x00\x0132\x16\x07\x01\x06\x07!2\x16\x0f\x01\x0e\x01+\x01\x15!2\x16\x0f\x01\x0e\x01+\x01\x15\x14\x06+\x01\"&=\x01!\"&?\x01>\x01;\x015!\"&?\x01>\x01;\x01&'\x01&6;\x012\x1f\x01\x162?\x016\x039\xfa\n\x05\x08\xfe\x94\x06\x05\x01\x0c\n\x06\x06x\x06\x18\n}\x01\x13\n\x06\x06x\x06\x18\n}\x0f\x0b\x94\x0b\x0f\xfe\xed\n\x06\x06x\x06\x18\n}\xfe\xed\n\x06\x06x\x06\x18\nv\x05\x06\xfe\x94\x08\x05\n\xfa\x19\x12\xa4\x08\x14\x08\xa4\x12\x04L\n\x08\xfe\x94\x06\x0c\x0c\x08\xa0\x08\x0cd\x0c\x08\xa0\x08\x0c\xae\x0b\x0f\x0f\x0b\xae\x0c\x08\xa0\x08\x0cd\x0c\x08\xa0\x08\x0c\x0c\x06\x01l\x08\n\x12\xa4\x08\x08\xa4\x12\x00\x00\x01\x00d\x00\x05\x04\x8c\x04\xae\x00;\x00\x00\x012\x17\x16\x17#4.\x03#\"\x0e\x03\x07!\x07!\x06\x15!\x07!\x1e\x0432>\x0353\x06\x07\x06#\"'.\x01'#7367#73>\x0176\x02\xe8\xf2p<\x06\xb5#4@9\x17\x13+820\x0f\x01{d\xfe\xd4\x06\x01\x96d\xfe\xd4 09B4\x15\x169@4#\xae\x1ebk\xa7\xcev$B\x0c\xd9dp\x01\x05\xdad\x86\x14>\x1fu\x04\xae\xbdhi-K0!\x0f\x0b\x1e.O2d22dJtB+\x0f\x0f\"0J+\xabku\x9e0\xaawd/5dW\x85%\x8d\x00\x00\x02\x00{\x00\x00\x04L\x04\xb0\x00>\x00G\x00\x00\x01!2\x1e\x05\x15\x1c\x01\x15\x14\x0e\x05+\x01\x07!2\x16\x0f\x01\x0e\x01+\x01\x15\x14\x06+\x01\"&=\x01!\"&?\x01>\x01;\x015!\"&?\x01>\x01;\x01\x1146\x17\x1132654&#\x01\xac\x01^CjB0\x16\x0c\x01\x01\x0c\x160BjC\xb2\x02\x01 \n\x06\x06x\x06\x18\n\x8a\x0b\n\x95\n\x0f\xfe\xf5\n\x06\x06x\x06\x18\nu\xfe\xf5\n\x06\x06x\x06\x18\nu\x0f\xb6\xcb@--@\x04\xb0\x1a$?2O*$\x0b\x0b\x0b$*P2@%\x1ad\x0c\x08\xa0\x08\x0c\xaf\x0b\x0e\x0f\n\xaf\x0c\x08\xa0\x08\x0cd\x0c\x08\xa0\x08\x0c\x01\xdb\n\x0f\xc8\xfe\xd4BVT@\x00\x00\x01\x00\xc8\x01\x90\x04L\x02\xbc\x00\x0f\x00\x00\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\xfa\x03 \x15\x1d\x1d\x15\xfc\xe0\x15\x1d\x1d\x02\xbc\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x00\x00\x00\x02\x00\xc8\x00\x00\x03\xe8\x04\xb0\x00%\x00A\x00\x00\x01\x15\x14\x06+\x01\x15\x14\x06\x07\x1e\x01\x1d\x0132\x16\x1d\x01!546;\x015467.\x01=\x01#\"&=\x01\x17\x15\x14\x16\x17\x1e\x01\x14\x06\x07\x0e\x01\x1d\x01!54&'.\x01467>\x01=\x01\x03\xe8\x1d\x152cQQc2\x15\x1d\xfc\xe0\x1d\x152cQQc2\x15\x1d\xc8A7\x1c \x1c7A\x01\x90A7\x1c \x1c7A\x04\xb0\x96\x15\x1dd[\x95##\x95[\x96\x1d\x15\x96\x96\x15\x1d\x96[\x95##\x95[d\x1d\x15\x96\xc8d\x01\x16\x1f\x0176\x03!'\x03\x02\xf6 \n\x88\x01\xd3\x1e\x14\x1e\xfbP\x1e\x14\x1e\x01\xd4\x87\n $\nop z\x01y\xb6\xc3\x04\xb3\x13#\x10\xbb\xfd\x16%\x15**\x15%\x02\xea\xb7\x10$\x14 \x10\x94\x96\x10\xfc\x1ep\x02\x16\x00\x00\x00\x00\x04\x00\x00\x00d\x04\xb0\x04L\x00\x0b\x00\x17\x00#\x007\x00\x00\x13!2\x16\x07\x01\x06\"'\x01&6\x17\x01\x16\x14\x07\x01\x06&5\x1146 \x016\x16\x15\x11\x14\x06'\x01&4\x07\x01\x16\x06#!\"&7\x0162\x1f\x01\x162?\x0162\x19\x04~\n\x05\x08\xfd\xcc\x08\x14\x08\xfd\xcc\x08\x05\x03\x01\x08\x08\x08\xfe\xf8\x08\n\n\x03\x8c\x01\x08\x08\n\n\x08\xfe\xf8\x08\\\x01l\x08\x05\n\xfb\x82\n\x05\x08\x01l\x08\x14\x08\xa4\x08\x14\x08\xa4\x08\x14\x04L\n\x08\xfd\xc9\x08\x08\x027\x08\n\xda\xfe\xf8\x08\x14\x08\xfe\xf8\x08\x05\n\x02&\n\x05\xfe\xf0\x01\x08\x08\x05\n\xfd\xda\n\x05\x08\x01\x08\x08\x14\x80\xfe\x94\x08\n\n\x08\x01l\x08\x08\xa4\x08\x08\xa4\x08\x00\x00\x00\x03\xff\xf0\xff\xf0\x04\xba\x04\xba\x00 \x00\x0d\x00\x10\x00\x00\x002\x1f\x01\x16\x14\x0f\x01'7\x13\x01' \x01\x05\x13\x03\xe0&\x0e\x99\x0d\x0dc\xd6_\"\xfd\x99\xd6\x02f\xfe\x1f\xfe\xb3n\x04\xba\x0d\x99\x0e&\x0e\\\xd6`\xfet\xfd\x9a\xd6\x02f\xfcjp\x01O\x00\x00\x00\x01\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x0f\x00\x00\x01\x1132\x16\x1d\x01!546;\x01\x11\x01!\x02\xbc\xfa\x15\x1d\xfc\xe0\x1d\x15\xfa\xfe\x0c\x04\xb0\x02\x8a\xfd\xda\x1d\x1522\x15\x1d\x02&\x02&\x00\x00\x00\x01\x00\x0e\x00\x08\x04L\x04\x9c\x00\x1f\x00\x00\x01%6\x16\x15\x11\x14\x06\x07\x06.\x01676\x17\x11\x05\x11\x14\x06\x07\x06.\x01676\x17\x1146\x01p\x02\x85'0SFO\x88$WOHB\xfd\xa8XAO\x88$WOHB\x1d\x03\xf9\xa3\x0f\x1e\"\xfc\xc17Q\x17\x19)mr\x19\x18\x10\x02 \x9b\xfd\xa2*`\x15\x1a)nq\x1a\x18\x11\x02\x7f&*\x00\x00\x00\x02\x00 \xff\xf8\x04\xbb\x04\xa7\x00\x1d\x00)\x00\x00\x002\x1e\x02\x15\x07\x17\x14\x07\x01\x16\x06\x0f\x01\x06\"'\x01\x06#'\x07\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x01\x90\xc8\xb6\x83N\x01\x01N\x01\x13\x17\x01\x16;\x1a)\x13\xfe\xedw\x8e\x05\x02d\xb6\x83NN\x83\x01r\xb0\x94VV\x94\xb0\x94VV\x04\xa7N\x83\xb6d\x02\x05\x8dy\xfe\xee\x1a%\x18:\x14\x14\x01\x12M\x01\x01N\x83\xb6\xc8\xb6\x83[V\x94\xb0\x94VV\x94\xb0\x94\x00\x01\x00d\x00X\x04\xaf\x04D\x00\x19\x00\x00\x01>\x02\x1e\x02\x15\x14\x0e\x03\x07.\x0454>\x02\x1e\x01\x02\x890{xuX6Cy\x84\xa8>>\xa7\x85xC8Zvxy\x03\xb5DH\x05-Sv@9y\x80\x7f\xb2UU\xb2\x7f\x80y9@vS-\x05H\x00\x00\x00\x01\xff\xd3\x00^\x04{\x04\x94\x00\x18\x00\x00\x01\x1362\x17\x13!2\x16\x07\x05\x13\x16\x06'%\x05\x06&7\x13%&63\x01\x97\x83\x07\x15\x07\x81\x01\xa5\x15\x06\x11\xfe\xaa\x82\x07\x0f\x11\xfe\xa9\xfe\xaa\x11\x0f\x07\x82\xfe\xa5\x11\x06\x14\x03 \x01a\x13\x13\xfe\x9f\x11\x0c\xf9\xfeo\x14\x0b\x0c\xf6\xf7\x0c\x0b\x14\x01\x90\xfb\x0c\x11\x00\x02\xff\xd3\x00^\x04{\x04\x94\x00\x18\x00\"\x00\x00\x01\x1362\x17\x13!2\x16\x07\x05\x13\x16\x06'%\x05\x06&7\x13%&63\x05#\x17\x077\x17'7#'\x01\x97\x83\x07\x15\x07\x81\x01\xa5\x15\x06\x11\xfe\xaa\x82\x07\x0f\x11\xfe\xa9\xfe\xaa\x11\x0f\x07\x82\xfe\xa5\x11\x06\x14\x01\xf3\xf0\xc5J\xc1\xc3J\xc0\xeaN\x03 \x01a\x13\x13\xfe\x9f\x11\x0c\xf9\xfeo\x14\x0b\x0c\xf6\xf7\x0c\x0b\x14\x01\x90\xfb\x0c\x11d\x8e\xe2\x8b\x8c\xe5\x8c\xd3\x00\x00\x01\x00\x00\x00\x00\x04\xb0\x04\xb0\x00&\x00\x00\x012\x16\x1d\x01\x14\x06#\x15\x14\x16\x17\x05\x1e\x01\x1d\x01\x14\x06#!\"&=\x01467%>\x01=\x01\"&=\x0146\x02X|\xb0>&\x0c \x01f \x0c\x0f\n\xfb\x82\n\x0f\x0c \x01f \x0c&>\xb0\x04\xb0\xb0|\xfa.hK\n\x17\x06\xe6\x05\x17\n]\n\x0f\x0f\n]\n\x17\x05\xe6\x06\x17\nKh.\xfa|\xb0\x00\x00\x00\x0d\x00\x00\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00#\x00'\x00+\x00/\x003\x007\x00G\x00K\x00O\x00S\x00W\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x1535)\x01\"\x06\x15\x11\x14\x163!265\x114&3\x1535\x05\x1535!\x1535\x05\x1535!\x1535\x07!\"\x06\x15\x11\x14\x163!265\x114&\x05\x1535!\x1535\x05\x1535!\x1535\x19\x04~\n\x0f\x0f\n\xfb\x82\n\x0f\x0fUd\x02\xa3\xfd\xda\n\x0f\x0f\n\x02&\n\x0f\x0fsd\xfc\x18d\x03 d\xfc\x18d\x03 d\xe1\xfd\xda\n\x0f\x0f\n\x02&\n\x0f\x0f\xfc\xefd\x03 d\xfc\x18d\x03 d\x04L\x0f\n\xfb\xe6\n\x0f\x0f\n\x04\x1a\n\x0fddd\x0f\n\xfe\xa2\n\x0f\x0f\n\x01^\n\x0fdd\xc8dddd\xc8ddddd\x0f\n\xfe\xa2\n\x0f\x0f\n\x01^\n\x0fddddd\xc8dddd\x00\x00\x04\x00\x00\x00\x00\x04L\x04L\x00\x0f\x00\x1f\x00/\x00?\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146)\x012\x16\x15\x11\x14\x06#!\"&5\x1146\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146)\x012\x16\x15\x11\x14\x06#!\"&5\x11462\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\x02m\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\xfd\xbd\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\x02m\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\x04L\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1d\xfd\xa8\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1d\x00\x00 \x00\x00\x00\x00\x04L\x04L\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\x7f\x00\x8f\x00\x00\x1332\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x01462\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\xfc\xf5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\xfc\xf5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x04L\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\xfep\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\xfep\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x00\x06\x00\x00\x00\x00\x04\xb0\x04L\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00\x00\x1332\x16\x1d\x01\x14\x06+\x01\"&=\x0146)\x012\x16\x1d\x01\x14\x06#!\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146)\x012\x16\x1d\x01\x14\x06#!\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146)\x012\x16\x1d\x01\x14\x06#!\"&=\x01462\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\x02\xbc\x15\x1d\x1d\x15\xfdD\x15\x1d\x1d\xfe\x85\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\x02\xbc\x15\x1d\x1d\x15\xfdD\x15\x1d\x1d\xfe\x85\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\x02\xbc\x15\x1d\x1d\x15\xfdD\x15\x1d\x1d\x04L\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\xfep\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\xfep\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x00\x00\x00\x00\x01\x00&\x00,\x04\xe8\x04 \x00\x17\x00\x00 \x0162\x1f\x01\x16\x14\x07\x01\x06\"'\x01&4?\x0162\x1f\x01\x162\x01\xd1\x02;\x08\x14\x07\xb1\x08\x08\xfc\xf1\x07\x15\x07\xfe\x80\x08\x08\xb1\x07\x14\x08\xab\x07\x16\x01\xdd\x02;\x08\x08\xb1\x07\x14\x08\xfc\xf0\x08\x08\x01\x80\x08\x14\x07\xb1\x08\x08\xab\x07\x00\x01\x00n\x00n\x04B\x04B\x00#\x00\x00\x01\x17\x16\x14\x07 \x01\x16\x14\x0f\x01\x06\"' \x01\x06\"/\x01&47 \x01&4?\x0162\x17 \x0162\x03\x88\xb2\x08\x08\xfe\xf5\x01\x0b\x08\x08\xb2\x08\x15\x07\xfe\xf4\xfe\xf4\x07\x15\x08\xb2\x08\x08\x01\x0b\xfe\xf5\x08\x08\xb2\x08\x15\x07\x01\x0c\x01\x0c\x07\x15\x04;\xb3\x08\x15\x07\xfe\xf4\xfe\xf4\x07\x15\x08\xb2\x08\x08\x01\x0b\xfe\xf5\x08\x08\xb2\x08\x15\x07\x01\x0c\x01\x0c\x07\x15\x08\xb2\x08\x08\xfe\xf5\x01\x0c\x07\x00\x03\x00\x17\xff\xeb\x04\xc5\x04\x99\x00\x19\x00%\x00I\x00\x00\x002\x1e\x02\x15\x14\x07\x01\x16\x14\x0f\x01\x06\"'\x01\x06#\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x0532\x16\x1d\x0132\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x01546\x01\x99\xc4\xb3\x82MN\x01,\x08\x08m\x07\x15\x08\xfe\xd4w\x8eb\xb4\x81MM\x81\x01o\xb3\x98XX\x98\xb3\x99XX\xfe\xbc\x96\n\x0fK\n\x0f\x0f\nK\x0f\n\x96\n\x0fK\n\x0f\x0f\nK\x0f\x04\x99M\x82\xb3b\x8dy\xfe\xd5\x08\x15\x08l\x08\x08\x01+MM\x81\xb4\xc4\xb3\x82MX\x99\xb3\x98XX\x98\xb3\x99#\x0f\nK\x0f\n\x96\n\x0fK\n\x0f\x0f\nK\x0f\n\x96\n\x0fK\n\x0f\x00\x00\x03\x00\x17\xff\xeb\x04\xc5\x04\x99\x00\x19\x00%\x005\x00\x00\x002\x1e\x02\x15\x14\x07\x01\x16\x14\x0f\x01\x06\"'\x01\x06#\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x05!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x01\x99\xc4\xb3\x82MN\x01,\x08\x08m\x07\x15\x08\xfe\xd4w\x8eb\xb4\x81MM\x81\x01o\xb3\x98XX\x98\xb3\x99XX\xfeX\x01^\n\x0f\x0f\n\xfe\xa2\n\x0f\x0f\x04\x99M\x82\xb3b\x8dy\xfe\xd5\x08\x15\x08l\x08\x08\x01+MM\x81\xb4\xc4\xb3\x82MX\x99\xb3\x98XX\x98\xb3\x99\x87\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x00\x00\x00\x00\x02\x00\x17\x00\x17\x04\x99\x04\xb0\x00\x0f\x00-\x00\x00\x0132\x16\x15\x11\x14\x06+\x01\"&5\x1146\x055\x16\x12\x15\x14\x0e\x02\".\x0254\x127\x15\x0e\x01\x15\x14\x1e\x012>\x0154&\x02&d\x15\x1d\x1d\x15d\x15\x1d\x1d\x01\x0f\xa7\xd2[\x9b\xd6\xea\xd6\x9b[\xd2\xa7g|r\xc5\xe8\xc5r|\x04\xb0\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1d\xe1\xa6>\xfe\xd9\xb8u\xd6\x9b[[\x9b\xd6u\xb8\x01'>\xa67\xc8xt\xc5rr\xc5tx\xc8\x00\x04\x00d\x00\x00\x04\xb0\x04\xb0\x00\x0f\x00\x1f\x00/\x00?\x00\x00\x0132\x16\x15\x11\x14\x06+\x01\"&5\x1146\x0132\x16\x15\x11\x14\x06+\x01\"&5\x1146\x0132\x16\x15\x11\x14\x06+\x01\"&5\x1146\x0532\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x04\x01\x96\n\x0f\x0f\n\x96\n\x0f\x0f\xfe\xde\x96\n\x0f\x0f\n\x96\n\x0f\x0f\xfe\xde\x96\n\x0f\x0f\n\x96\n\x0f\x0f\xfe\xde\x96\n\x0f\x0f\n\x96\n\x0f\x0f\x04\xb0\x0f\n\xfb\x82\n\x0f\x0f\n\x04~\n\x0f\xfep\x0f\n\xfd\x12\n\x0f\x0f\n\x02\xee\n\x0f\xfe\xd4\x0f\n\xfe>\n\x0f\x0f\n\x01\xc2\n\x0f\xc8\x0f\n\xfa\n\x0f\x0f\n\xfa\n\x0f\x00\x00\x00\x00\x02\x00\x1a\x00\x1b\x04\x96\x04\x96\x00G\x00O\x00\x00\x012\x1f\x02\x16\x1f\x017\x16\x17\x07\x17\x16\x1f\x02\x16\x15\x14\x0f\x02\x06\x0f\x01\x17\x06\x07'\x07\x06\x0f\x02\x06#\"/\x02&/\x01\x07&'7'&/\x02&54?\x026?\x01'67\x1776?\x026\x12\"\x06\x14\x16264\x02X!)&\x051-\x05\x86=+P\x03\x19\x0e\x01\x98\x05\x05\x98\x01\x0f\x18\x03P08\x86\x05,2\x05&+\x1f!)&\x051-\x05\x86<,P\x03\x19\x0d\x02\x97\x06\x06\x97\x02\x0d\x19\x03P/:\x85\x05-1\x05&+x\xb2~~\xb2~\x04\x96\x05\x98\x01\x0e\x19\x02P09\x86\x05,1\x06&+\x1e\"(&\x061,\x05\x86=,Q\x03\x19\x0e\x02\x97\x05\x05\x97\x02\x0e\x19\x03Q09\x86\x05-0\x06&* !(&\x060-\x05\x86=,P\x02\x19\x0e\x01\x98\x05\xfe\x99~\xb1~~\xb1\x00\x07\x00d\x00\x00\x04\xb0\x05\x14\x00\x13\x00\x17\x00!\x00%\x00)\x00-\x001\x00\x00\x01!2\x16\x1d\x01!2\x16\x1d\x01!5463!546\x17\x15!5\x01\x11\x14\x06#!\"&5\x11\x17\x113\x113\x113\x113\x113\x113\x113\x11\x01\xf4\x01,);\x01\x13\n\x0f\xfb\xb4\x0f\n\x01\x13;)\x01,\x01,;)\xfdD);dddddddd\x05\x14;)d\x0f\nKK\n\x0fd);ddd\xfe\xd4\xfc\xe0);;)\x03 d\xfdD\x02\xbc\xfdD\x02\xbc\xfdD\x02\xbc\xfdD\x02\xbc\x00\x01\x00\x0c\x00\x00\x05\x08\x04\xd1\x00\x1f\x00\x00\x13\x0162\x17\x01\x16\x06+\x01\x11\x14\x06+\x01\"&5\x11!\x11\x14\x06+\x01\"&5\x11#\"&\x12\x02l\x08\x15\x07\x02`\x08\x05\n\xaf\x0f\n\xfa\n\x0f\xfe\xd4\x0f\n\xfa\n\x0f\xaf\n\x05\x02j\x02`\x07\x07\xfd\xa0\x08\n\xfd\xc1\n\x0f\x0f\n\x01w\xfe\x89\n\x0f\x0f\n\x02?\n\x00\x02\x00d\x00\x00\x03\xe8\x04\xb0\x00\x11\x00\x17\x00\x00\x01\x11\x14\x163!\x11\x14\x06#!\"&5\x11463\x01#\"&=\x01\x02X;)\x01,\x1d\x15\xfc\xe0\x15\x1d\x1d\x15\x03R\xfa\x15\x1d\x04\xb0\xfep);\xfdv\x15\x1d\x1d\x15\x04L\x15\x1d\xfep\x1d\x15\xfa\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x1b\x000\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x0532\x16\x15\x1132\x16\x1d\x01\x14\x06+\x01\"&5\x1146\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\xbf\xe8\xc5rr\xc5\xe8\xc5rr\xfe|2\n\x0f\xaf\n\x0f\x0f\n\xfa\n\x0f\x0f\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b;r\xc5\xe8\xc5rr\xc5\xe8\xc5\x0d\x0f\n\xfe\xed\x0f\n2\n\x0f\x0f\n\x01^\n\x0f\x00\x00\x00\x00\x02\xff\x9c\x00\x00\x05\x14\x04\xb0\x00\x0b\x00\x0f\x00\x00)\x01\x03#\x03!\x013\x033\x033\x01\x033\x03\x05\x14\xfd\xe6)\xf2)\xfd\xe6\x01\xaf\xd1\x15\xa2\x14\xd0\xfe\x9e\x1b\xe0\x1b\x01\x90\xfep\x04\xb0\xfe\xd4\x01,\xfep\xfe\xd4\x01,\x00\x00\x00\x00\x02\x00d\x00\x00\x04\xb0\x04\xb0\x00\x15\x00/\x00\x00\x0132\x16\x15\x1132\x16\x07\x01\x06\"'\x01&6;\x01\x1146\x0132\x16\x15\x11\x14\x06#!\"&5\x1146;\x012\x16\x1d\x01!546\x02&\xc8\x15\x1d\xbf\x14\x0b\x0d\xfe\xb9\x0d&\x0d\xfe\xb9\x0d\x0b\x14\xbf\x1d\x02T2\n\x0f\x0f\n\xfb\xe6\n\x0f\x0f\n2\n\x0f\x03\x84\x0f\x04\xb0\x1d\x15\xfe>\x17\x10\xfep\x10\x10\x01\x90\x10\x17\x01\xc2\x15\x1d\xfc\xe0\x0f\n\xfe\xa2\n\x0f\x0f\n\x01^\n\x0f\x0f\n\xaf\xaf\n\x0f\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x1b\x001\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x0532\x16\x15\x1132\x16\x07\x03\x06\"'\x03&6;\x01\x1146\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\xbf\xe8\xc5rr\xc5\xe8\xc5rr\xfe|\x96\n\x0f\x89\x15\n\x0d\xdf\x0d&\x0d\xdf\x0d\n\x15\x89\x0f\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b;r\xc5\xe8\xc5rr\xc5\xe8\xc5\x0d\x0f\n\xfe\xed\x17\x10\xfe\xed\x10\x10\x01\x13\x10\x17\x01\x13\n\x0f\x00\x00\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x1b\x001\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&%\x13\x16\x06+\x01\x11\x14\x06+\x01\"&5\x11#\"&7\x1362\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\xbf\xe8\xc5rr\xc5\xe8\xc5rr\xfe\xe7\xdf\x0d\n\x15\x89\x0f\n\x96\n\x0f\x89\x15\n\x0d\xdf\x0d&\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b;r\xc5\xe8\xc5rr\xc5\xe8\xc5\x01\xfe\xed\x10\x17\xfe\xed\n\x0f\x0f\n\x01\x13\x17\x10\x01\x13\x10\x00\x00\x00\x00\x02\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x19\x009\x00\x00\x13!2\x16\x17\x13\x16\x15\x11\x14\x06\x07\x06#!\"&'&5\x1347\x13>\x01\x05!\"\x06\x07\x03\x06\x16;\x012\x16\x1f\x01\x1e\x01;\x0126?\x01>\x01;\x0126'\x03.\x01\xe1\x02\xee\n\x13\x03\xba\x07\x08\x05\x0c\x19\xfb\xb4\x0c\x1e\x02\x06\x01\x07\xb9\x03\x13\x02\x97\xfd\xd4\n\x12\x02W\x02\x0c\n\x96\n\x13\x02&\x02\x13\n\xfa\n\x13\x02&\x02\x13\n\x96\n\x0c\x02W\x02\x12\x04\xb0\x0e\n\xfdt\x18\x19\xfeW\x0c\x1e\x02\x06\x08\x04\x0d\x19\x01\xa9\x19\x18\x02\x8c\n\x0e\xc8\x0e\x0b\xfe>\x0b\x0e\x0e\n\x98\n\x0e\x0e\n\x98\n\x0e\x0e\x0b\x01\xc2\x0b\x0e\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x1b\x00'\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x05\x17\x16\x14\x0f\x01\x06&5\x1146\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\xbf\xe8\xc5rr\xc5\xe8\xc5rr\xfe\x8b\xfd\x11\x11\xfd\x10\x18\x18\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b;r\xc5\xe8\xc5rr\xc5\xe8\xc5]\xbe\x0c$\x0c\xbe\x0c\x0b\x15\x01\x90\x15\x0b\x00\x01\x00\x17\x00\x17\x04\x99\x04\xb0\x00(\x00\x00\x0176\x16\x15\x11\x14\x06#!\"&?\x01&#\"\x0e\x01\x14\x1e\x012>\x0153\x14\x0e\x02\".\x024>\x0232\x03\xb3\x87\x07\x0b\x0f\n\xfe\x96\x0b\x04\x07\x85m\x81t\xc5rr\xc5\xe8\xc5r\x96[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6u\xc0\x04$\x87\x07\x04\x0b\xfe\x96\n\x0f\x0b\x07\x85Lr\xc5\xe8\xc5rr\xc5tu\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[\x00\x00\x00\x00\x02\x00\x17\x00\x01\x04\x99\x04\xb0\x00\x1a\x005\x00\x00\x0176\x16\x15\x11\x14\x06#!\"&?\x01&#\"\x0e\x01\x15#4>\x0232\x133\x14\x0e\x02#\"'\x07\x06&5\x11463!2\x16\x0f\x01\x1632>\x01\x03\xb3\x87\x07\x0b\x0f\x0b\xfe\x97\x0b\x04\x07\x86n\x81t\xc5r\x96[\x9b\xd6u\xc0\xeb\x96[\x9b\xd6u\xc0\x9c\x86\x07\x0b\x0f\x0b\x01h\n\x05\x08\x85n\x82t\xc5r\x04$\x87\x07\x04\x0b\xfe\x97\x0b\x0f\x0b\x07\x86Kr\xc5tu\xd6\x9b[\xfd\xbfu\xd6\x9b[v\x86\x08\x05\n\x01h\x0b\x0f\x0b\x07\x85Lr\xc5\x00\x00\x00\n\x00d\x00\x00\x04\xb0\x04\xb0\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\x7f\x00\x8f\x00\x9f\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x05!\"\x06\x15\x11\x14\x163!265\x114&\x0532\x16\x1d\x01\x14\x06+\x01\"&=\x01463!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x0732\x16\x1d\x01\x14\x06+\x01\"&=\x01463!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x0732\x16\x1d\x01\x14\x06+\x01\"&=\x01463!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x0732\x16\x1d\x01\x14\x06+\x01\"&=\x01463!2\x16\x1d\x01\x14\x06#!\"&=\x0146}\x04\x1a\n\x0f\x0f\n\xfb\xe6\n\x0f\x0f\x03\xc0\xfc\xae\n\x0f\x0f\n\x03R\n\x0f\x0f\xfd\x082\n\x0f\x0f\n2\n\x0f\x0f\xd2\x01\xc2\n\x0f\x0f\n\xfe>\n\x0f\x0f\xbe2\n\x0f\x0f\n2\n\x0f\x0f\xd2\x01\xc2\n\x0f\x0f\n\xfe>\n\x0f\x0f\xbe2\n\x0f\x0f\n2\n\x0f\x0f\xd2\x01\xc2\n\x0f\x0f\n\xfe>\n\x0f\x0f\xbe2\n\x0f\x0f\n2\n\x0f\x0f\xd2\x01\xc2\n\x0f\x0f\n\xfe>\n\x0f\x0f\x04\xb0\x0f\n\xfb\x82\n\x0f\x0f\n\x04~\n\x0f\xc8\x0f\n\xfc\xae\n\x0f\x0f\n\x03R\n\x0fd\x0f\n2\n\x0f\x0f\n2\n\x0f\x0f\n2\n\x0f\x0f\n2\n\x0f\xc8\x0f\n2\n\x0f\x0f\n2\n\x0f\x0f\n2\n\x0f\x0f\n2\n\x0f\xc8\x0f\n2\n\x0f\x0f\n2\n\x0f\x0f\n2\n\x0f\x0f\n2\n\x0f\xc8\x0f\n2\n\x0f\x0f\n2\n\x0f\x0f\n2\n\x0f\x0f\n2\n\x0f\x00\x00\x00\x00\x02\x00\x00\x00\x00\x04L\x04\xb0\x00\x19\x00#\x00\x00\x0154&#!\"\x06\x1d\x01#\"\x06\x15\x11\x14\x163!265\x114&#!546;\x012\x16\x1d\x01\x03\x84uS\xfe\xd4Rvd);;)\x03\x84);;)\xfd\xa8\x1e\x14\xc8\x14\x1e\x03 \xc8SuvR\xc8;)\xfd\xa8);;)\x02X);\x96\x15\x1d\x1d\x15\x96\x00\x02\x00d\x00\x00\x04L\x04L\x00 \x007\x00\x00\x1332\x16\x15\x11#\x1146\x052\x17\x16\x15\x11\x14\x07\x0e\x03#\".\x01'.\x02#\"\x07\x06#\"'&5\x11>\x0176\x1e\x03\x17\x1e\x023276}2\n\x0fd\x0f\x03\xc0\x04\x05\x10\x03!C@1\x1c\x1a?*'),G\x1eUK\x07\x08\x06\x05\x0e\x16x;\x17(.\x139\x04)-E\x1dgP\x07\x04L\x0f\n\xfb\xcd\x043\n\x0f0\x02\x06\x11\xfe[\x06\x06;P$\x0d\x0d\x0e\x0e\x0f\x0f\x0f9\x05\x03\x07\x0f\x01\xb67W\x03\x02\x03\x0b\x06\x14\x01\x0e\x0e\x0eW\x08\x00\x00\x03\x00\x00\x00\x00\x04\xb0\x04\x97\x00!\x001\x00A\x00\x00\x002\x1e\x02\x15\x11\x14\x06+\x01\"&5\x114.\x01 \x0e\x01\x15\x11\x14\x06+\x01\"&5\x114>\x01\x0332\x16\x15\x11\x14\x06+\x01\"&5\x1146!32\x16\x15\x11\x14\x06+\x01\"&5\x1146\x01\xe4\xe8\xde\xa3c\x0f\n2\n\x0f\x8d\xe4\xfe\xfa\xe4\x8d\x0f\n2\n\x0fc\xa3*\xa0\x08\x0c\x0c\x08\xa0\x08\x0c\x0c\x02`\xa0\x08\x0c\x0c\x08\xa0\x08\x0c\x0c\x04\x97c\xa3\xdet\xfe\xd4\n\x0f\x0f\n\x01,\x7f\xd1rr\xd1\x7f\xfe\xd4\n\x0f\x0f\n\x01,t\xde\xa3\xfd\xc0\x0c\x08\xfe4\x08\x0c\x0c\x08\x01\xcc\x08\x0c\x0c\x08\xfe4\x08\x0c\x0c\x08\x01\xcc\x08\x0c\x00\x00\x00\x00\x02\x00\x00\x00\xd3\x04G\x03\xdd\x00\x15\x009\x00\x00\x01%6\x16\x15\x11\x14\x06'%&+\x01\"&5\x1146;\x012\x05762\x1f\x01\x16\x14\x0f\x01\x17\x16\x14\x0f\x01\x06\"/\x01\x07\x06\"/\x01&4?\x01'&4?\x0162\x17\x01A\x01\x02 \x0c\x0c \xfe\xfe\x15\x19\xfa\n\x0f\x0f\n\xfa\x19\x02Xx\x07\x14\x07\"\x07\x07xx\x07\x07\"\x07\x14\x07xx\x07\x14\x07\"\x07\x07ww\x07\x07\"\x07\x14\x07\x03.\xac\x06\x07\n\xfd\x12\n\x07\x06\xac\x0e\x0f\n\x01^\n\x0f\x84x\x07\x07\"\x07\x14\x07xx\x07\x14\x07\"\x07\x07ww\x07\x07\"\x07\x14\x07xx\x07\x14\x07\"\x08\x08\x00\x00\x00\x00\x02\x00\x00\x00\xd3\x03r\x03\xdd\x00\x15\x00/\x00\x00\x01%6\x16\x15\x11\x14\x06'%&+\x01\"&5\x1146;\x012%3\x16\x17\x16\x15\x14\x07\x06\x0f\x01\"/\x01.\x017654'&6?\x016\x01A\x01\x02 \x0c\x0c \xfe\xfe\x15\x19\xfa\n\x0f\x0f\n\xfa\x19\x01\xd2\x04\n\x06`Z\x06\x0b\x03 \x07\x1d\x07\x03\x06HN\x06\x03\x08\x1d\x07\x03.\xac\x06\x07\n\xfd\x12\n\x07\x06\xac\x0e\x0f\n\x01^\n\x0fd\x01 \x81\xa1\x9a\x7f \x01\x01\x06\x17\x07\x13\x08g~\x84j\x08\x14\x07\x16\x05\x00\x00\x00\x00\x03\x00\x00\x00\xc4\x04b\x03\xec\x00\x1b\x001\x00K\x00\x00\x013\x16\x17\x16\x15\x14\x06\x07\x06\x07#\"/\x01.\x017654&'&6?\x016\x05%6\x16\x15\x11\x14\x06'%&+\x01\"&5\x1146;\x012%3\x16\x17\x16\x15\x14\x07\x06\x0f\x01\"/\x01.\x017654'&6?\x016\x03\xc7\x03\x0b\x06\x87D@\x07\n\x03 \x07*\x08\x02\x06o;7\x06\x02 *\x07\xfd\x82\x01\x02 \x0c\x0c \xfe\xfe\x15\x19\xfa\n\x0f\x0f\n\xfa\x19\x01\xd2\x04\n\x06`Z\x06\x0b\x03 \x07\x1d\x07\x03\x06HN\x06\x03\x08\x1d\x07\x03\xec\x01 \xb3\xd9i\xcbT \x01\x06\"\x06\x14\x08\x96\xb2Z\xacG \x14\x06!\x05\xbe\xac\x06\x07\n\xfd\x12\n\x07\x06\xac\x0e\x0f\n\x01^\n\x0fd\x01 \x81\xa1\x9a\x7f \x01\x01\x06\x17\x07\x13\x08g~\x84j\x08\x15\x06\x16\x05\x00\x00\x00\x00\x0d\x00\x00\x00\x00\x04\xb0\x04\xb0\x00 \x00\x15\x00\x19\x00\x1d\x00!\x00%\x00-\x00;\x00?\x00C\x00G\x00K\x00O\x00\x00\x013\x15#\x15!\x15#\x11!\x01#\x153\x15!\x11#\x11#5!\x05\x11!\x11!\x11!\x11\x05#53\x05#53\x013\x11!\x11353\x013\x15#\x15#5#535#5!\x05\x11!\x11\x07#53\x05#53\x01#53\x05!5!\x01\xf4dd\xfepd\x01\xf4\x02\xbc\xc8\xc8\xfe\xd4\xc8d\x02X\xfb\xb4\x01,\x01\x90\x01,\xfc\xe0dd\x02\xbcdd\xfdD\xc8\xfe\x0c\xc8d\x01\xf4\xc8d\xc8dd\xc8\x01,\xfdD\x01,ddd\x03\x84dd\xfe\x0cdd\x01\xf4\xfe\xd4\x01,\x03\x84ddd\x02X\xfe\x0cd\xc8\x01,\x01,\xc8d\xfe\xd4\x01,\xfe\xd4\x01,\xc8ddd\xfe\x0c\xfe\x0c\x01\xf4d\xfe\xd4dddd\xc8d\xc8\xfe\xd4\x01,\xc8ddd\xfe\xd4ddd\x00\x00\x00\x00 \x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x03\x00\x07\x00\x0b\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00#\x00\x007#\x113\x13#\x113\x01#\x113\x13#\x113\x01#\x113\x01!5!\x17#53\x17#53\x05#53ddd\xc8dd\x01\x90\xc8\xc8\xc8dd\x01,\xc8\xc8\xfc\xe0\xfe\xd4\x01,\xc8dd\xc8dd\x01,\xc8\xc8\xc8\x03\xe8\xfc\x18\x03\xe8\xfc\x18\x03\xe8\xfc\x18\x03\xe8\xfc\x18\x03\xe8\xfbPdd[[[[[\x00\x00\x02\x00\x00\x00\n\x04\xa6\x04\xb0\x00\x0d\x00\x15\x00\x00 \x01\x16\x14\x07\x01\x06\"'\x01\x13463\x04&\"\x06\x14\x1626\x01\xf4\x02\xaa\x08\x08\xfe0\x08\x14\x08\xfdV\x01\x0f\n\x01C;S;;S;\x04\xb0\xfdV\x08\x14\x08\xfe0\x08\x08\x02\xaa\x01\xdb\n\x0f\xcd;;T;;\x00\x00\x00\x00\x03\x00\x00\x00\n\x05\xd2\x04\xb0\x00\x0d\x00\x19\x00!\x00\x00 \x01\x16\x14\x07\x01\x06\"'\x01\x13463!\x01\x16\x14\x07\x01\x06\"/\x01 \x01\x04&\"\x06\x14\x1626\x01\xf4\x02\xaa\x08\x08\xfe0\x08\x14\x08\xfdV\x01\x0f\n\x03\x06\x02\xaa\x08\x08\xfe0\x08\x14\x088\x01\xa8\xfdD\xfe\xd3;S;;S;\x04\xb0\xfdV\x08\x14\x08\xfe0\x08\x08\x02\xaa\x01\xdb\n\x0f\xfdV\x08\x14\x08\xfe0\x08\x088\x01\xaa\x02\xbc\xcd;;T;;\x00\x00\x00\x00\x01\x00d\x00\x00\x04\xb0\x04\xb0\x00&\x00\x00\x01!2\x15\x11\x14\x0f\x01\x06&5\x114&#!\"\x0f\x01\x06\x163!2\x16\x15\x11\x14\x06#!\"&5\x114?\x016\x01,\x039K\x12@\x08\n\x0f\n\xfdD\x19\x12@\x08\x05\n\x02\xbc\n\x0f\x0f\n\xfc\xae\n\x0f\x12\x8b\x12\x04\xb0K\xfc|\x19\x12@\x08\x05\n\x03\xb6\n\x0f\x12@\x08\n\x0f\n\xfcJ\n\x0f\x0f\n\x03\xcf\x19\x12\x8b\x12\x00\x00\x00\x01\x00\xc8\xff\xff\x04L\x04\xb0\x00\n\x00\x00\x13!2\x16\x15\x11 \x01\x1146\xfa\x03 \x15\x1d\xfe>\xfe>\x1d\x04\xb0\x1d\x15\xfb\x82\x01\xbc\xfeC\x04\x7f\x15\x1d\x00\x00\x00\x00\x03\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x15\x00E\x00U\x00\x00\x01!\"\x06\x07\x03\x06\x1f\x01\x1e\x013!26?\x016'\x03.\x01\x01#\"\x06\x0f\x01\x0e\x01#!\"&/\x01.\x01+\x01\"\x06\x15\x11\x14\x16;\x0126=\x01463!2\x16\x1d\x01\x14\x16;\x01265\x114&\x01!\"\x06\x0f\x01\x06\x163!26/\x01.\x01\x036\xfeD\x0b\x10\x01N\x07\x0e9\x06\x17\n\x01\xc2\n\x17\x06>\x0e\x07S\x01\x10\x01V\x96\n\x16\x04N\x04\x16\n\xfd\xda\n\x16\x04N\x04\x16\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x02\xee\n\x0f\x0f\n\x96\n\x0f\x0f\xfe\xb1\xfe\x0c\n\x13\x02&\x02\x0b\n\x02X\n\x0b\x02&\x02\x13\x04\xb0\x0f\n\xfe\xd3\x18\x15l \x0c\x0c l\x15\x18\x01-\n\x0f\xfep\x0d \x9c \x0d\x0d \x9c \x0d\x0f\n\xfdv\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x02\x8a\n\x0f\xfd\xa8\x0e\n\x98\n\x0e\x0e\n\x98\n\x0e\x00\x00\x00\x00\x04\x00\x00\x00d\x04\xb0\x04L\x00\x1d\x00!\x00)\x001\x00\x00\x0132\x1e\x02\x1f\x0132\x16\x15\x11\x14\x06#!\"&5\x1146;\x01>\x04\x01\x1535\x04\"\x06\x14\x16264$2\x16\x14\x06\"&4\x01\xf4\xc88]4$\x07\x06\x96);;)\xfc\x18);;)\x96\x02 '3]\x01\xc8d\xfe\xcf\xbe\x87\x87\xbe\x87\xfe\xefV<\x01?\x01\x01\x03!\x03\x02\xa9\x01\x81\x14(\x12% \n\xfe_5,\x11R\xfey:\"\x0b *2\x1e\xfe\x938\x1c\x0c\x1a\x07\x07\x01\x8f\xac\x01T\xa2\x04\xaf\xfc\x1a2*\x13\x15\x01\x02BBW-\xde\x91Y\".\x1c\x0cBB\x18\x1c\x0c%\x0d\x0d\x03\xee\xfdZ\x01\xc9\x00\x00\x00\x00\x03\x00d\x00\x00\x03\xf0\x04\xb0\x00'\x002\x00;\x00\x00\x01\x1e\x06\x15\x14\x0e\x03#!5>\x015\x114.\x04'5\x052\x1e\x02\x15\x14\x0e\x02\x07%32654.\x02+\x01\x1132654&+\x01\x02\xf1\x05\x1350;*\x1d7Xml0\xfe\x0c);\x01\x06\x0b\x17!\x1a\x01\xd79uc>\x1f--\x10\xfe\x8f\x8bNi\x11*S>v\xd8PR}^\x9f\x02\x81\x01\x07\x18\x1d3:R.CuN7\x1aY\x073(\x03;\x18\x14\x1c\x0b\x10 \x07G\x01)IsC3[:+ 1aJ);4\x1b\xfc\xaeePZ\x81\x00\x00\x01\x00\xc8\x00\x00\x03o\x04\xb0\x00\x19\x00\x00\x01\x17\x0e\x01\x07\x03\x06\x16\x17\x15!567\x1364.\x04'&'5\x03m\x02SB\x07\x84 ,J\xfe\x0c\xba\x0e\xad\x03\x03\x0f\x0c\x1f\x15\x17\x0d\x06\x04\xb09\x135(\xfc\xb91(\x06aa\x10R\x03@\x11\x1a\x13\x10 \x0b\x06\x07\x03\x029\x00\x00\x00\x00\x02\xff\xb5\x00\x00\x05\x14\x04\xb0\x00%\x00/\x00\x00\x01#4.\x05+\x01\x11\x14\x16\x1f\x01\x15!52>\x035\x11#\"\x0e\x05\x15#\x11!\x05#\x113\x07'3\x11#7\x05\x142\x08\x0b\x19\x13&\x18\x19\xc82\x19\x19\xfep\x04\x0e\"\x1a\x16\xc8\x19\x18&\x13\x19\x0b\x082\x03\xe8\xfb\x9bKK}}KK}\x03\x84\x15 \x15\x0e\x08\x03\x01\xfc\xae\x16\x19\x01\x02dd\x01\x05 \x15\x0e\x03R\x01\x03\x08\x0e\x15 \x15\x01,\xc8\xfc\xe0\xa7\xa7\x03 \xa7\x00\x02\x00!\xff\xb5\x04\x8f\x04\xb0\x00%\x00/\x00\x00\x01#4.\x05+\x01\x11\x14\x16\x1f\x01\x15!52>\x035\x11#\"\x0e\x05\x15#\x11!\x13\x075!\x15'7\x15!5\x04L2\x08\x0b\x19\x13&\x18\x19\xc82\x19\x19\xfep\x04\x0e\"\x1a\x16\xc8\x19\x18&\x13\x19\x0b\x082\x03\xe8C\xa7\xfc\xe0\xa7\xa7\x03 \x03\x84\x15 \x15\x0e\x08\x03\x01\xfdv\x16\x19\x01\x02dd\x01\x05 \x15\x0e\x02\x8a\x01\x03\x08\x0e\x15 \x15\x01,\xfb\x82}KK}}KK\x00\x04\x00\x00\x00\x00\x04\xb0\x04L\x00\x0f\x00\x1f\x00/\x00?\x00\x00\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x01462\x02X\x15\x1d\x1d\x15\xfd\xa8\x15\x1d\x1d\x15\x03\xe8\x15\x1d\x1d\x15\xfc\x18\x15\x1d\x1d\x15\x03 \x15\x1d\x1d\x15\xfc\xe0\x15\x1d\x1d\x15\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x1d\x04L\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x04\x00\x00\x00\x00\x04\xb0\x04L\x00\x0f\x00\x1f\x00/\x00?\x00\x00\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x03!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x03!2\x16\x1d\x01\x14\x06#!\"&=\x0146\xfa\x02\xbc\x15\x1d\x1d\x15\xfdD\x15\x1d\x1d\xb3\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x1d\xdd\x02\xbc\x15\x1d\x1d\x15\xfdD\x15\x1d\x1d\xb3\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x1d\x04L\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x04\x00\x00\x00\x00\x04\xb0\x04L\x00\x0f\x00\x1f\x00/\x00?\x00\x00\x015463!2\x16\x1d\x01\x14\x06#!\"&\x015463!2\x16\x1d\x01\x14\x06#!\"&\x135463!2\x16\x1d\x01\x14\x06#!\"&\x015463!2\x16\x1d\x01\x14\x06#!\"&\x01\xf4\x1d\x15\x02X\x15\x1d\x1d\x15\xfd\xa8\x15\x1d\xfep\x1d\x15\x03\xe8\x15\x1d\x1d\x15\xfc\x18\x15\x1d\xc8\x1d\x15\x03 \x15\x1d\x1d\x15\xfc\xe0\x15\x1d\xfe\xd4\x1d\x15\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x03\xb6d\x15\x1d\x1d\x15d\x15\x1d\x1d\xfe\xe9d\x15\x1d\x1d\x15d\x15\x1d\x1d\xfe\xe9d\x15\x1d\x1d\x15d\x15\x1d\x1d\xfe\xe9d\x15\x1d\x1d\x15d\x15\x1d\x1d\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04L\x00\x0f\x00\x1f\x00/\x00?\x00\x00\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x01462\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x1d\x15\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x1d\x15\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x1d\x15\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x1d\x04L\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x08\x00\x00\x00\x00\x04\xb0\x04L\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\x7f\x00\x00\x1332\x16\x1d\x01\x14\x06+\x01\"&=\x0146)\x012\x16\x1d\x01\x14\x06#!\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146)\x012\x16\x1d\x01\x14\x06#!\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146)\x012\x16\x1d\x01\x14\x06#!\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146)\x012\x16\x1d\x01\x14\x06#!\"&=\x01462d\x15\x1d\x1d\x15d\x15\x1d\x1d\x01A\x03 \x15\x1d\x1d\x15\xfc\xe0\x15\x1d\x1d\xfe\xe9d\x15\x1d\x1d\x15d\x15\x1d\x1d\x01A\x03 \x15\x1d\x1d\x15\xfc\xe0\x15\x1d\x1d\xfe\xe9d\x15\x1d\x1d\x15d\x15\x1d\x1d\x01A\x03 \x15\x1d\x1d\x15\xfc\xe0\x15\x1d\x1d\xfe\xe9d\x15\x1d\x1d\x15d\x15\x1d\x1d\x01A\x03 \x15\x1d\x1d\x15\xfc\xe0\x15\x1d\x1d\x04L\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x00\x06\xff\x9c\x00\x00\x04\xb0\x04L\x00\x03\x00\x13\x00#\x00*\x00:\x00J\x00\x00!#\x11;\x022\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x05\x075#535\x05!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x01\x90dd\x96d\x15\x1d\x1d\x15d\x15\x1d\x1d\x15\x01\xf4\x15\x1d\x1d\x15\xfe\x0c\x15\x1d\x1d\xfe\xfa\xa7\xc8\xc8\x01\xc2\x01,\x15\x1d\x1d\x15\xfe\xd4\x15\x1d\x1d\x15\x02X\x15\x1d\x1d\x15\xfd\xa8\x15\x1d\x1d\x04L\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfa}KdK\xaf\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x00\x00\x06\x00\x00\x00\x00\x05\x14\x04L\x00\x0f\x00\x13\x00#\x00*\x00:\x00J\x00\x00\x1332\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x01#\x113\x01!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x053\x15#\x15'7\x05!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x01462d\x15\x1d\x1d\x15d\x15\x1d\x1d\x03gdd\xfc\xae\x01\xf4\x15\x1d\x1d\x15\xfe\x0c\x15\x1d\x1d\x04/\xc8\xc8\xa7\xa7\xfb\xe6\x01,\x15\x1d\x1d\x15\xfe\xd4\x15\x1d\x1d\x15\x02X\x15\x1d\x1d\x15\xfd\xa8\x15\x1d\x1d\x04L\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfb\xb4\x04L\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xc8dK}}\xaf\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfe\xd4\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x00\x00\x00\x02\x00\x00\x00\xc8\x04\xb0\x03\xe8\x00\x0f\x00\x12\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146 \x02K\x02\xee\x1f,,\x1f\xfd\x12\x1f,,\x04\x84\xfe\xd4\x01,\x03\xe8,\x1f\xfdv\x1f,,\x1f\x02\x8a\x1f,\xfdD\x01,\x01,\x00\x03\x00\x00\x00\x00\x04\xb0\x04L\x00\x0f\x00\x17\x00\x1f\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x117\x05'\x01\x13\x11\x042\x16\x14\x06\"&4,\x04X\x12\x1a\x1a\x12\xfb\xa8\x12\x1a\x1aJ\xf7\x01*J\x01%\xec\xfc\xd2pNNpN\x04L\x1a\x12\xfc\x0c\x12\x1a\x1a\x12\x03\xf4\x12\x1ad\xfd\x1f\xb6\x83\x9c\x01>\xfe\xe0\x01\xf4tNoOOo\x00\x00\x00\x00\x02\x00\xdb\x00\x05\x046\x04\x91\x00\x16\x00\x1e\x00\x00\x012\x1e\x01\x15\x14\x07\x0e\x01\x0f\x01.\x04'&54>\x02\x16\"\x06\x14\x16264\x02\x88u\xc6sFE\xb266 !^Xm)\x08!fh\x98H\x84uX\xa3yH\xc3\x82\xb8\x81\x81\xb8\x00\x00\x00\x02\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x17\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x01\x11\"\x0e\x01\x14\x1e\x01\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01Kt\xc5rr\xc5\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b\xfco\x03Vr\xc5\xe8\xc5r\x00\x00\x02\x00u\x00\x03\x03\xdf\x05\x0f\x00\x1a\x005\x00\x00\x01\x1e\x06\x15\x14\x0e\x03\x07.\x0354>\x05\x03\x0e\x02\x17\x1e\x04\x17\x166?\x016&'.\x02'&76#&\x02*\x15IOWN>%3Vp}?T\x9b|J$?LWPI\xbc\x17)(\x03\x01\x1b!1\x1c\x13\x15\x16\x02\x06\x02 \x05\x12)\x0c\x1a \x02\x08\x08\x05\x0fH\x8fuwsu\x87EG\x80^F&\x04\x05:c\x97YE\x87vsxv\x90\xfd\xfe!K\x82:%A'#\x0e\x08\x07\x0c\x10\"\n\x18\x07\x04\x10A)Y\xb6\x0b\x01\x00\x00\x00\x03\x00\x00\x00\x00\x04\xcb\x04l\x00\x0c\x00*\x00/\x00\x00\x017>\x02\x1e\x01\x17\x1e\x01\x0f\x02%!2\x17\x07!\"\x06\x15\x11\x14\x163!26=\x017\x11\x14\x06#!\"&5\x1146 \x01\x077\x01\x03\xe8l\x02\x06\x14\x15\x1d\x0e\x16\n\x05\x06l\xfd\x05\x01\x9027\xbb\xfe\x90);;)\x01\xf4);\xc8\xbb\xa3\xfep\xa5\xb9\xb9\x038\xfe\x96\xa17\x01c\x03\xf5s\x01\x02\x02\x04\x0f\x0e\x16*\x0b\ns\xc8\x0d\xbb;)\xfe\x0c);;)\xb6\xc8\xfe\xb4\xa5\xb9\xb9\xa5\x01\x90\xa5\xb9\xfe\xd7\xfe\x962\xaa\x01c\x00\x02\x00\x00\x00\x00\x04\x93\x04L\x00\x1b\x006\x00\x00\x01!\x06\x07#\"\x06\x15\x11\x14\x163!2657\x15\x14\x06#!\"&5\x1146\x05\x01\x16\x14\x07\x01\x06&'5&\x0e\x03\x07>\x0675>\x01\x01^\x01i\xa44\xc3);;)\x01\xf4);\xc8\xb9\xa5\xfep\xa5\xb9\xb9\x02\x7f\x01S\x08\x08\xfe\xac\x07\x0b\x01\x1a9dTX\x1a\n.9I@F*\x13\x01\x0b\x04L\x926;)\xfe\x0c);;)\x99g\xa5\xb9\xb9\xa5\x01\x90\xa5\xb9\x1b\xfe\xd3\x07\x15\x07\xfe\xce\x06\x04 \xcb\x01\x02\x0d\x160!;bA4\x1d\x14\x07\x01\xd2\n\x05\x00\x00\x00\x00\x02\x00\x00\x00\x00\x04\x9d\x04L\x00\x1d\x005\x00\x00\x01!2\x17\x07!\"\x06\x15\x11\x14\x163!26=\x017\x15\x14\x06#!\"&5\x1146 \x0162\x1f\x01\x16\x14\x07\x01\x06\"/\x01&4?\x0162\x1f\x01\x162\x01^\x01^\x01\x08\x08\x14\x08\x01\x04\x07\x05\n\xaa\xc8\n\x08\x01\x08\x08\x08\xfe\xf8\x08\n\xc8\xaa\n\x05\x07\xfe\xfc\x08\x14\x08\xfe\xf8\x08\x05\n\xaf\xc8\n\x08\xfe\xf8\x08\x08\x01\x08\x08\n\xc8\xaf\n\x05\x03\x96\x01\x08\x08\x08\xfe\xf8\x08\n\xc8\xad\n\x04\x07\xfe\xfc\x07\x15\x07\xfe\xf7\x07\x04\n\xad\xc8\n\x08\xfe\xf8\x08\x08\x01\x08\x08\n\xc8\xad\n\x04\x07\x01 \x07\x15\x07\x01\x04\x07\x04\n\xad\xc8\n\x00\x01\x00\xc8\x00\x00\x03\x84\x04L\x00\x19\x00\x00\x1332\x16\x15\x11\x016\x16\x15\x11\x14\x06'\x01\x11\x14\x06+\x01\"&5\x1146\xfad\x15\x1d\x01\xd0\x0f\x15\x15\x0f\xfe0\x1d\x15d\x15\x1d\x1d\x04L\x1d\x15\xfeJ\x01\xc5\x0e\x08\x15\xfc\x18\x15\x08\x0e\x01\xc5\xfeJ\x15\x1d\x1d\x15\x03\xe8\x15\x1d\x00\x00\x00\x01\x00\x00\x00\x00\x04\xb0\x04L\x00#\x00\x00\x1332\x16\x15\x11\x016\x16\x15\x11\x016\x16\x15\x11\x14\x06'\x01\x11\x14\x06'\x01\x11\x14\x06+\x01\"&5\x11462d\x15\x1d\x01\xd0\x0f\x15\x01\xd0\x0f\x15\x15\x0f\xfe0\x15\x0f\xfe0\x1d\x15d\x15\x1d\x1d\x04L\x1d\x15\xfeJ\x01\xc5\x0e\x08\x15\xfeJ\x01\xc5\x0e\x08\x15\xfc\x18\x15\x08\x0e\x01\xc5\xfeJ\x15\x08\x0e\x01\xc5\xfeJ\x15\x1d\x1d\x15\x03\xe8\x15\x1d\x00\x00\x00\x01\x00\x9d\x00\x19\x04\xb0\x043\x00\x15\x00\x00\x01\x11\x14\x06'\x01\x11\x14\x06'\x01&47\x016\x16\x15\x11\x016\x16\x04\xb0\x15\x0f\xfe0\x15\x0f\xfe\x14\x0f\x0f\x01\xec\x0f\x15\x01\xd0\x0f\x15\x04\x1a\xfc\x18\x15\x08\x0e\x01\xc5\xfeJ\x15\x08\x0e\x01\xe0\x0e*\x0e\x01\xe0\x0e\x08\x15\xfeJ\x01\xc5\x0e\x08\x00\x00\x00\x01\x00\xc8\x00\x16\x043\x046\x00\x0b\x00\x00\x13\x01\x16\x14\x07\x01\x06&5\x1146\xf3\x03.\x12\x12\xfc\xd2\x12\x19\x19\x042\xfe\x0e\x0b\x1e\x0b\xfe\x0e\x0b\x0e\x15\x03\xe8\x15\x0e\x00\x02\x00\xc8\x00d\x03\x84\x03\xe8\x00\x0f\x00\x1f\x00\x00\x1332\x16\x15\x11\x14\x06+\x01\"&5\x1146!32\x16\x15\x11\x14\x06+\x01\"&5\x1146\xfa\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x01\xa5\xc8\x15\x1d\x1d\x15\xc8\x15\x1d\x1d\x03\xe8\x1d\x15\xfc\xe0\x15\x1d\x1d\x15\x03 \x15\x1d\x1d\x15\xfc\xe0\x15\x1d\x1d\x15\x03 \x15\x1d\x00\x00\x01\x00\xc8\x00d\x04L\x03\xe8\x00\x0f\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04L\x1d\x15\xfc\xe0\x15\x1d\x1d\x15\x03 \x15\x1d\x03\xb6\xfc\xe0\x15\x1d\x1d\x15\x03 \x15\x1d\x1d\x00\x00\x00\x00\x01\x00\x00\x00\x19\x04\x13\x043\x00\x15\x00\x00\x01\x1146\x17\x01\x16\x14\x07\x01\x06&5\x11\x01\x06&5\x1146\x17\x01\xf4\x15\x0f\x01\xec\x0f\x0f\xfe\x14\x0f\x15\xfe0\x0f\x15\x15\x0f\x02d\x01\xb6\x15\x08\x0e\xfe \x0e*\x0e\xfe \x0e\x08\x15\x01\xb6\xfe;\x0e\x08\x15\x03\xe8\x15\x08\x0e\x00\x00\x01\xff\xfe\x00\x02\x04\xb3\x04O\x00#\x00\x00\x0172\x16\x15\x13\x14\x06#\x07\"&5\x03\x01\x06&5\x03\x01\x06&5\x0346\x17\x01\x0346\x17\x01\x0346\x04\x18d\x14\x1e\x05\x1d\x15d\x15\x1d\x02\xfe1\x0e\x15\x02\xfe2\x0f\x15\x05\x15\x0f\x01\xd2\x02\x15\x0f\x01\xd2\x02\x1d\x04N\x01\x1d\x15\xfc\x18\x15\x1d\x01\x1d\x15\x01\xb5\xfe:\x0f \x15\x01\xb5\xfe9\x0e \x14\x03\xe8\x15 \x0f\xfe>\x01\xb6\x14 \x0e\xfe=\x01\xb6\x15\x1d\x00\x00\x01\x01,\x00\x00\x03\xe8\x04L\x00\x19\x00\x00\x0132\x16\x15\x11\x14\x06+\x01\"&5\x11\x01\x06&5\x1146\x17\x01\x1146\x03Rd\x15\x1d\x1d\x15d\x15\x1d\xfe0\x0f\x15\x15\x0f\x01\xd0\x1d\x04L\x1d\x15\xfc\x18\x15\x1d\x1d\x15\x01\xb6\xfe;\x0e\x08\x15\x03\xe8\x15\x08\x0e\xfe;\x01\xb6\x15\x1d\x00\x00\x02\x00d\x00\xc8\x04\xb0\x04H\x00\x0b\x00\x1b\x00\x00 \x01\x16\x06#!\"&7\x0162\x01!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x02\xae\x01\xf5\x0f \x16\xfb\xee\x16 \x0f\x01\xf5\x0f*\xfd\xf7\x03\xe8\x15\x1d\x1d\x15\xfc\x18\x15\x1d\x1d\x049\xfd\xe4\x0f\x16\x16\x0f\x02\x1c\x0f\xfdH\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x01\x00\x88\xff\xfc\x03u\x04J\x00\x05\x00\x00 \x02\x07 \x01\x03u\xfe\xa0\x01`\xc5\xfd\xd8\x02(\x03\x84\xfe\x9f\xfe\x9f\xc6\x02(\x02&\x00\x00\x00\x00\x01\x01;\xff\xfc\x04(\x04J\x00\x05\x00\x00 \x01' \x017\x04(\xfd\xd9\xc6\x01a\xfe\x9f\xc6\x02#\xfd\xd9\xc6\x01a\x01a\xc6\x00\x02\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x003\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x05#\"\x06\x1d\x01#\"\x06\x1d\x01\x14\x16;\x01\x15\x14\x16;\x0126=\x01326=\x014&+\x0154&\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01}d\x15\x1d\x96\x15\x1d\x1d\x15\x96\x1d\x15d\x15\x1d\x96\x15\x1d\x1d\x15\x96\x1d\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b\xba\x1d\x15\x96\x1d\x15d\x15\x1d\x96\x15\x1d\x1d\x15\x96\x1d\x15d\x15\x1d\x96\x15\x1d\x00\x00\x00\x00\x02\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x1f\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x01!\"\x06\x1d\x01\x14\x163!26=\x014&\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x02E\xfe\x0c\x15\x1d\x1d\x15\x01\xf4\x15\x1d\x1d\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b\xfe~\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x02\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x003\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0f\x01'&\"\x0f\x01\x06\x14\x1f\x01\x07\x06\x14\x1f\x01\x162?\x01\x17\x162?\x0164/\x01764/\x01\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\xe5\x19 xx \x19 \x8d xx \x8d \x19 xx \x19 \x8d xx \x8d\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b\xad xx \x8d \x19 xx \x19 \x8d xx \x8d \x19 xx \x19 \x8d\x00\x02\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00$\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x01'&\"\x0f\x01\x06\x14\x1f\x01\x1627\x0164/\x01&\"\x07\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\x15T\x07\x15\x08\x8b\x07\x07\xf2\x07\x15\x07\x01w\x07\x07\x8b\x07\x15\x07\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b\xfe1U\x07\x07\x8b\x08\x14\x08\xf1\x08\x08\x01w\x07\x15\x08\x8b\x07\x07\x00\x00\x00\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00;\x00K\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x05\"\x0e\x03\x15\x14;\x01\x167>\x0132\x16\x15\x14\x06\x07\"\x0e\x05\x07\x06\x16;\x012>\x0354.\x03\x13#\"\x06\x1d\x01\x14\x16;\x0126=\x014&\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01?\x1d\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x05#\"\x06\x1d\x01\x14\x16;\x0126=\x014&\x03#\"\x06\x1d\x01\x14\x16;\x01\x15#\"\x06\x1d\x01\x14\x163!26=\x014&+\x01\x114&\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\x96\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\xfa\n\x0f\x0f\nKK\n\x0f\x0f\n\x01^\n\x0f\x0f\nK\x0f\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9bV\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\xfe\xd4\x0f\n2\n\x0f\xc8\x0f\n2\n\x0f\x0f\n2\n\x0f\x01\x13\n\x0f\x00\x02\x00\x00\x00\x00\x04\xb0\x04\xb0\x00/\x00_\x00\x00\x0132\x16\x1d\x01\x1e\x01\x1732\x16\x1d\x01\x14\x06+\x01\x0e\x01\x07\x15\x14\x06+\x01\"&=\x01.\x01'#\"&=\x0146;\x01>\x017546\x13\x15\x14\x06+\x01\"&=\x01\x0e\x01\x0732\x16\x1d\x01\x14\x06+\x01\x1e\x01\x17546;\x012\x16\x1d\x01>\x017#\"&=\x0146;\x01.\x01\x02\x0d\x96\n\x0fg\x97\x1b\xc2\n\x0f\x0f\n\xc2\x1b\x97g\x0f\n\x96\n\x0fg\x97\x1b\xc2\n\x0f\x0f\n\xc2\x1b\x97g\x0f\xb9\x0f\n\x96\n\x0fDf\x17\xa8\n\x0f\x0f\n\xa8\x17fD\x0f\n\x96\n\x0fDf\x17\xa8\n\x0f\x0f\n\xa8\x17f\x04\xb0\x0f\n\xc2\x1b\x97g\x0f\n\x96\n\x0fg\x97\x1b\xc2\n\x0f\x0f\n\xc2\x1b\x97g\x0f\n\x96\n\x0fg\x97\x1b\xc2\n\x0f\xfe\xcd\xa8\n\x0f\x0f\n\xa8\x17fD\x0f\n\x96\n\x0fDf\x17\xa8\n\x0f\x0f\n\xa8\x17fD\x0f\n\x96\n\x0fDf\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x1b\x00?\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x07\x17\x16\x14\x0f\x01\x17\x16\x14\x0f\x01\x06\"/\x01\x07\x06\"/\x01&4?\x01'&4?\x0162\x1f\x01762\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\xbf\xe8\xc5rr\xc5\xe8\xc5rr\x9a@\x07\x07||\x07\x07@\x07\x15\x07||\x07\x15\x07@\x07\x07||\x07\x07@\x07\x15\x07||\x07\x15\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b;r\xc5\xe8\xc5rr\xc5\xe8\xc5Z@\x07\x15\x07||\x07\x15\x07@\x07\x07||\x07\x07@\x07\x15\x07||\x07\x15\x07@\x07\x07||\x07\x00\x00\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x1b\x000\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x07\x17\x16\x14\x07\x01\x06\"/\x01&4?\x0162\x1f\x01762\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\xbf\xe8\xc5rr\xc5\xe8\xc5rr\x83j\x07\x07\xfe\xc0\x08\x14\x08\xca\x08\x08j\x07\x15\x07O\xc5\x07\x15\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b;r\xc5\xe8\xc5rr\xc5\xe8\xc5}j\x07\x15\x07\xfe\xbf\x07\x07\xcb\x07\x15\x07j\x08\x08O\xc5\x07\x00\x00\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x18\x00!\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x05\"\x0e\x01\x15\x14\x17\x01&\x17\x01\x1632>\x0154\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01Kt\xc5rA\x02Ki\xf5\xfd\xb8hst\xc5r\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b;r\xc5txi\x02KA\xd0\xfd\xb8>r\xc5ts\x00\x00\x00\x00\x01\x00\x17\x00S\x04\xb0\x03\xf9\x00\x15\x00\x00\x13\x016\x16\x15\x11!2\x16\x1d\x01\x14\x06#!\x11\x14\x06'\x01&4'\x02\n\x10\x17\x02&\x15\x1d\x1d\x15\xfd\xda\x17\x10\xfd\xf6\x10\x02F\x01\xab\x0d\n\x15\xfe\xdd\x1d\x15\xc8\x15\x1d\xfe\xdd\x15\n\x0d\x01\xab\x0d&\x00\x00\x00\x00\x01\x00\x00\x00S\x04\x99\x03\xf9\x00\x15\x00\x00 \x01\x16\x14\x07\x01\x06&5\x11!\"&=\x01463!\x1146\x02\x7f\x02\n\x10\x10\xfd\xf6\x10\x17\xfd\xda\x15\x1d\x1d\x15\x02&\x17\x03\xf1\xfeU\x0d&\x0d\xfeU\x0d\n\x15\x01#\x1d\x15\xc8\x15\x1d\x01#\x15\n\x00\x00\x00\x01\x00\xb7\x00\x00\x04]\x04\x99\x00\x15\x00\x00 \x01\x16\x06#!\x11\x14\x06+\x01\"&5\x11!\"&7\x0162\x02\xaa\x01\xab\x0d\n\x15\xfe\xdd\x1d\x15\xc8\x15\x1d\xfe\xdd\x15\n\x0d\x01\xab\x0d&\x04\x89\xfd\xf6\x10\x17\xfd\xda\x15\x1d\x1d\x15\x02&\x17\x10\x02\n\x10\x00\x00\x00\x01\x00\xb7\x00\x17\x04]\x04\xb0\x00\x15\x00\x00\x0132\x16\x15\x11!2\x16\x07\x01\x06\"'\x01&63!\x1146\x02&\xc8\x15\x1d\x01#\x15\n\x0d\xfeU\x0d&\x0d\xfeU\x0d\n\x15\x01#\x1d\x04\xb0\x1d\x15\xfd\xda\x17\x10\xfd\xf6\x10\x10\x02\n\x10\x17\x02&\x15\x1d\x00\x00\x01\x00\x00\x00\xb7\x04\x99\x04]\x00\x17\x00\x00 \x01\x16\x14\x07\x01\x06&5\x11\x0e\x03\x07>\x047\x1146\x02\x7f\x02\n\x10\x10\xfd\xf6\x10\x17^\xb0\xa5\x81$\x05,[\x87\xc7~\x17\x04U\xfeU\x0d&\x0d\xfeU\x0d\n\x15\x01#\x02$DuMi\xb1\x9dqF\x07\x01\x06\x15\n\x00\x02\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x15\x00+\x00\x00\x01!2\x16\x15\x11\x14\x06/\x01\x07\x06\"/\x01&4?\x01'&6\x01!\"&5\x1146\x1f\x01762\x1f\x01\x16\x14\x0f\x01\x17\x16\x06\x03R\x01,\x15\x1d\x15\x0e^\xf9\x08\x14\x08j\x07\x07\xf9^\x0e\x08\xfe!\xfe\xd4\x15\x1d\x15\x0e^\xf9\x08\x14\x08j\x07\x07\xf9^\x0e\x08\x04\xb0\x1d\x15\xfe\xd4\x15\x08\x0e^\xf9\x07\x07j\x08\x14\x08\xf9^\x0e\x15\xfbP\x1d\x15\x01,\x15\x08\x0e^\xf9\x07\x07j\x08\x14\x08\xf9^\x0e\x15\x00\x00\x00\x02\x00I\x00I\x04g\x04g\x00\x15\x00+\x00\x00\x01\x17\x16\x14\x0f\x01\x17\x16\x06#!\"&5\x1146\x1f\x01762\x01!2\x16\x15\x11\x14\x06/\x01\x07\x06\"/\x01&4?\x01'&6\x03\xf6j\x07\x07\xf9^\x0e\x08\x15\xfe\xd4\x15\x1d\x15\x0e^\xf9\x08\x14\xfd\x0c\x01,\x15\x1d\x15\x0e^\xf9\x08\x14\x08j\x07\x07\xf9^\x0e\x08\x04`j\x08\x14\x08\xf9^\x0e\x15\x1d\x15\x01,\x15\x08\x0e^\xf9\x07\xfd\xf1\x1d\x15\xfe\xd4\x15\x08\x0e^\xf9\x07\x07j\x08\x14\x08\xf9^\x0e\x15\x00\x00\x00\x00\x03\x00\x17\x00\x17\x04\x99\x04\x99\x00\x0f\x00\x1f\x00/\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x05#\"\x06\x17\x13\x1e\x01;\x01267\x136&\x03#\"\x06\x1d\x01\x14\x16;\x0126=\x014&\x01\xe3\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b[[\x9b\x01\xb3\xd0\x14\x18\x04:\x04#\x146\x14#\x04:\x04\x181\x96\n\x0f\x0f\n\x96\n\x0f\x0f\x04\x99[\x9b\xd6\xea\xd6\x9b[[\x9b\xd6\xea\xd6\x9b\xba\x1d\x14\xfe\xd2\x14\x1d\x1d\x14\x01.\x14\x1d\xfe\x0c\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x00\x00\x00\x00\x05\x00\x00\x00\x00\x04\xb0\x04\xb0\x00I\x00U\x00a\x00h\x00o\x00\x00\x012\x16\x1f\x01\x16\x1f\x01\x16\x17\x1676?\x0167632\x16\x1f\x01\x16\x1f\x02\x1e\x01;\x012\x16\x1d\x01\x14\x06+\x01\"\x06\x1d\x01!\x11#\x11!54&+\x01\"&=\x0146;\x012654?\x0167>\x04\x05\x07\x06\x16;\x0126/\x01.\x01\x05'&\x06\x0f\x01\x06\x16;\x0126\x13!\"&5\x11)\x01\x11\x14\x06#!\x11\x01\x04 \x14\x05\x05\x16\x16\xc4\x15\x0f\x1d\x08\x0b&\xc4\x16\x17\x11\x15\x170\x0d\x0d\x0e\x04\x19\x08\x01\x0f\n=\n\x0f\x0f\n2\n\x0f\xfep\xc8\xfep\x0f\n2\n\x0f\x0f\n=\x0b\x0e \x19\x05\x0e\x02\x06\x15\x16\x1f\x02\x9d\xa6\x07\x04\n\xdb\n\n\x033\x03\x10\xfe5\xb1\x08\x10\x033\x03\n\n\xe7\x0b\x03\x1e\xfe\x89\n\x0f\x01\x90\x02X\x0f\n\xfe\x89\x04\xb0\x04\x02\x02\n\x0dv\x0d\x0b\x15 \x0d\x16v\x0d\n\x07!\x11\x10\x15\x18{, \x0b\x0f\n2\n\x0f\x0f\n\xaf\x01,\xfe\xd4\xaf\n\x0f\x0f\n2\n\x0f\x06\x05\x040\x80\x19\x14\x03\x08\x16\x11\x0ey\xa2\x07\n\x0e\n\x95\n\x04\xaa\x9d\x07\x04\n\x8f\n\x0e\n\xfcr\x0f\n\x01w\xfe\x89\n\x0f\x01\x90\x00\x00\x00\x00\x02\x00\x00\x00\x0c\x04\xaf\x04\xa6\x00+\x00I\x00\x00\x016\x16\x15\x06\x02\x0e\x04.\x01'&\x07&\x0e\x01\x0f\x01\x06&547>\x017>\x01'.\x01>\x017>\x06\x17&\x06\x07\x0e\x01\x0f\x01\x0e\x04\x07\x0e\x01\x1667>\x027>\x037>\x01\x04\x8d\x08\x1a\x02-Bla\x8bb\x8eD8=\x11\x04\x113\x1b\x99\x1a\x16*\x08U\x18\x13 \x03 \x02\x10:1'Ra\\\x87{\xc0%\x08\x1d\x1f&\xa2=>8\\tYR\x17\x18\x0e\x12-!\x19\x8aq[Fak[)\x16\x04\x04\xa6\x03\x13\x08\xb2\xfe\xdd\xc8\x95X1\x11\x08\x0b\x0b\x0c\x01\x01\x02\x1b\x1b\x99\x18\x13\"@&\x08J\x15\x11<\x1f7_\x7f\x85?3J5%#\x1b/D \x18&/q!!\x1e6ROg58<\x04'(\x1e[@1%@_\x7fU2\x14\x00\x01\x00]\x00\x1e\x04r\x04\xcf\x00O\x00\x00\x01\x0e\x01\x1e\x04\x17.\x07>\x017\x1e\x03\x06\x07\x0e\x04\x07\x06'&767>\x04.\x01'\x16\x0e\x03&'.\x01'&>\x047\x06\x1e\x037>\x01.\x02'&>\x03\x02\x8d'\x1f\n'8GB \x04\x1b\n\x18\n\x10\x03\x01 \x12\x0e`\x8aH \x06\x10\x0d>JS>\x16H7\x1f\x12\x06\x0b\x0d'+\" \x16NA\n\x155M[`/Pg\x02\x02\x04\x05\x16!;(\x08\x06\x1d'2\x18\x1f\x0f\x18\"&\x07\x0f\"IbY\x04\xcfC\x80e\\D9$\x0c\x078\x178\x1e6#1%)\x12*\x83\x91\xa7\x97J7gG: \x06\x16\x0b\x06\x0d\x03\x04\x05 8G\\au9h\xaaoK\x1d\x07\x15$\x9c]\x1754<\x04\x05&\x06\x17\x16\x15\x14\x06\"&5476&\x07\x06\x07\x0e\x01\x17\x1e\x042>\x0376&'&\x05\x07\x0e\x01\x17\x16\x17\x166?\x016&'&'.\x01\x02\x06\xa4\x9d{nO9\x1c\x1c:On{\x9d\xa2\x9d{nO:\x1c\x1c9On{\x02\x0f\x0f\x06\x08\x19\xb0\xf8\xb0\x17\x08\x07\x0eFZ\x0d\x04\x0b\x162Z_\x83\x88\x83_Z2\x16\x0b\x04\x0cZ\xfd\xff#\x0f %8\x10-\x0e#\x0e\x03\x0f,-\x0b\"\x04F-I\\b\\I*I\\b\\I--I\\b\\I*I\\b\\I\xdc\x0f\x06\x139>|\xb0\xb0|;7\x13\x06\x0fEs\x101\x12$F^D10E^E$\x121\x11u\x1e$\x0f/\x12D0\x0d\x04\x0f\"\x0f%\x0f,I\x12\x04\x00\x00\x00\x04\xff\xdc\x00\x00\x04\xd4\x04\xb0\x00\x14\x00'\x00;\x00L\x00\x00!#7.\x0454>\x0532\x1773\x137\x1e\x01\x15\x14\x0e\x03\x077>\x0176&'&%\x06\x07\x0e\x01\x17\x1e\x04\x177.\x015476&\x17\x07\x0e\x01\x17\x16\x17\x166?\x02'&'.\x01\x02P\x94\x1f[\xa9vY,\x1c9On{\x9dR=A \x94&/l\x89'Pj\x98R.Mv&\x0b\x04\x0c6\xfdQFZ\x0d\x04\x0b\x12*HLh5)k\x8f\x17\x08\x07|#\x0f %8\x10-\x0e\x0c\x16\x03,-\x0b\"x\x14atzb\x1b\x15I\\b\\I-\x0fy\xfeR\xb5U\xd64\x1aZrnc\x1a\xad1\x88?\x121\x11FrEs\x101\x12\x1e\xfe\xad\xfe\xbb\x0e1\x14)\x14\x0d\x0c\xf9\xfe\xf9]\x14@\x15\x10 \x80\x80 \x10\x15@\x14]\x01\x07\xf9\x0c\x0d\x14)\x141\x0e\x01E\x01S>\x00\x00\x00\x11\x00\x00\x00\x00\x04L\x04\xb0\x00\x1d\x00'\x00+\x00/\x003\x007\x00;\x00?\x00C\x00G\x00K\x00O\x00S\x00W\x00[\x00_\x00c\x00\x00\x0132\x16\x1d\x0132\x16\x1d\x01!546;\x01546;\x012\x16\x1d\x01!546\x01\x11\x14\x06#!\"&5\x11\x17\x15353\x15353\x15353\x15353\x1535\x05\x15353\x15353\x15353\x15353\x1535\x05\x15353\x15353\x15353\x15353\x1535\x03Rd\x15\x1d2\x15\x1d\xfb\xb4\x1d\x152\x1d\x15d\x15\x1d\x01\xf4\x1d\x01\x0f\x1d\x15\xfc\x18\x15\x1ddddddddddd\xfc|ddddddddd\xfc|ddddddddd\x04\xb0\x1d\x152\x1d\x15\x96\x96\x15\x1d2\x15\x1d\x1d\x1522\x15\x1d\xfep\xfd\x12\x15\x1d\x1d\x15\x02\xee\xc8dddddddddd\xc8dddddddddd\xc8dddddddddd\x00\x00\x00\x03\x00\x00\x00\x19\x05w\x04\x97\x00\x19\x00%\x007\x00\x00\x01\x17\x16\x14\x0f\x01\x06&=\x01#\x01!\"&=\x0146;\x01\x013546\x01\x07'#\"&=\x01463!\x01\x17\x16\x14\x0f\x01\x06&=\x01#'7\x173546\x04o\xf9\x0f\x0f\xf9\x0e\x15\x9f\xfd\xa8\xfe\xdd\x15\x1d\x1d\x15\xd1\x02X\xf1\x15\xfd\xa9\x8dz\xd1\x15\x1d\x1d\x15\x01#\x03\x1a\xf9\x0f\x0f\xf9\x0e\x15\xf1\xb5\x8dz\x9f\x15\x04\x8d\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xfd\xa8\x1d\x15d\x15\x1d\x02X\x96\x15\x08\xfe\x98\x8dz\x1d\x15d\x15\x1d\xfeM\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xb5\x8dz\x96\x15\x08\x00\x00\x00\x01\x00\x00\x00\x00\x04\xb0\x04L\x00\x12\x00\x00\x13!2\x16\x15\x11\x14\x06#!\x01\x11#\"&5\x1146d\x03\xe8);;)\xfd\xac\xfe\xd0d);;\x04L;)\xfd\xa8);\xfe\xd4\x01,;)\x02X);\x00\x00\x00\x03\x00d\x00\x00\x04L\x04\xb0\x00 \x00\x13\x00?\x00\x00\x1332\x16\x1d\x01!546!32\x16\x1d\x01!546\x01\x11\x14\x0e\x05\".\x055\x11!\x15\x14\x15\x1c\x01\x1e\x062>\x06&54=\x01\x96\xc8\x15\x1d\xfe\xd4\x1d\x02\xd1\xc8\x15\x1d\xfe\xd4\x1d\x01\x0f\x06\x18(Lf\x9c\xc0\x9cfL(\x18\x06\x01,\x03\x07\x0d\x14\x1f'6B6'\x1f\x13\x0f\x05\x05\x01\x04\xb0\x1d\x15\xfa\xfa\x15\x1d\x1d\x15\xfa\xfa\x15\x1d\xfep\xfe\xd4)IjV\\>((>\\VjI)\x01,\xfa \x12\x15+'%!\x1b\x16\x10\x08 \x10\x17\x1c!%'*\x15\x11\x08\xfa\x00\x00\x00\x01\xff\xff\x00\xd4\x04L\x03\xc2\x00\x05\x00\x00\x01\x07 \x01'\x01\x04L\xc6\xfe\x9f\xfe\x9f\xc5\x02'\x01\x9b\xc7\x01a\xfe\x9f\xc7\x02'\x00\x01\x00\x00\x00\xee\x04M\x03\xdc\x00\x05\x00\x00 \x027 \x01\x04M\xfd\xda\xfd\xd9\xc6\x01a\x01a\x03\x15\xfd\xd9\x02'\xc7\xfe\x9f\x01a\x00\x00\x00\x00\x02\xffQ\x00d\x05_\x03\xe8\x00\x14\x00)\x00\x00\x01!2\x16\x15\x1132\x16\x0f\x01\x06\"/\x01&6;\x01\x11!%\x17\x16\x06+\x01\x11!\x17!\"&5\x11#\"&?\x0162\x01\x94\x02\xea\x15\x1d\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xfe\x83\xfe\x1c\xe6\x0e\x08\x15\x96\x01\x81\xd7\xfd\x12\x15\x1d\x96\x15\x08\x0e\xe6\x0e*\x03\xe8\x1d\x15\xfd\xd9\x15\x0e\xf9\x0f\x0f\xf9\x0e\x15\x01\x91\xb8\xf9\x0e\x15\xfep\xc8\x1d\x15\x02&\x15\x0e\xf9\x0f\x00\x00\x01\x00\x06\x00\x00\x04\x9e\x04\xb0\x000\x00\x00\x1332\x16\x1f\x01!2\x16\x07\x03\x0e\x01#!\x17!2\x16\x14\x06+\x01\x15\x14\x06\"&=\x01!\x15\x14\x06\"&=\x01#\"&/\x01\x03#\"&468^\x11\x1c\x04&\x03\x80\x18\x1e\x05d\x05,!\xfd\x870\x02\x17\x15\x1d\x1d\x152\x1d*\x1d\xfe\xd4\x1d*\x1d\x1f\x12\x1d\x06\x05\xc96\x14\x1e\x1e\x04\xb0\x16\x10\xa2%\x18\xfe%\x15+\xc8\x1d*\x1d2\x15\x1d\x1d\x1522\x15\x1d\x1d\x152\x14 \n\x03\xc1\x1d*\x1d\x00\x00\x00\x00\x02\x00\x00\x00\x00\x04\xb0\x04L\x00\x0b\x00\x0f\x00\x00\x01\x15!53463!2\x16\x15\x05!\x11!\x04\xb0\xfbP\xc8;)\x01,);\xfdD\x04\xb0\xfbP\x03\xe8dd);;)\xc8\xfc\xe0\x00\x02\x00\x00\x00\x00\x05\xdc\x04L\x00\x0c\x00\x10\x00\x00\x13\x03\x113463!2\x16\x15!\x15\x05\x01!\x01\xc8\xc8\xc8;)\x01,*:\x01\xf4\x01,\xfe\xd4\xfbP\x01,\x03 \xfep\x02X);;)\xc8d\xfdD\x02\xbc\x00\x01\x01E\x00\x00\x03k\x04\xaf\x00\x1b\x00\x00\x01\x17\x16\x06+\x01\x1132\x16\x0f\x01\x06\"/\x01&6;\x01\x11#\"&?\x0162\x02{\xe6\x0e\x08\x15\x96\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\x96\x15\x08\x0e\xe6\x0e*\x04\xa0\xf9\x0e\x15\xfd\xa7\x15\x0e\xf9\x0f\x0f\xf9\x0e\x15\x02Y\x15\x0e\xf9\x0f\x00\x00\x00\x01\x00\x01\x01D\x04\xaf\x03k\x00\x1b\x00\x00\x01\x17\x16\x14\x0f\x01\x06&=\x01!\x15\x14\x06/\x01&4?\x016\x16\x1d\x01!546\x03\xa8\xf9\x0e\x0e\xf9\x0f\x15\xfd\xa8\x15\x0f\xf9\x0e\x0e\xf9\x0f\x15\x02X\x15\x03`\xe5\x0f)\x0f\xe5\x0f \x14\x97\x97\x14 \x0f\xe5\x0f)\x0f\xe5\x0f \x15\x95\x95\x15 \x00\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04\xb0\x00 \x00\x19\x00\x1d\x00!\x00\x00\x01\x03.\x01#!\"\x06\x07\x03\x05!\"\x06\x1d\x01\x14\x163!26=\x014&\x0553\x15353\x15\x04\x91\xac\x05$\x14\xfd`\x14$\x05\xac\x04-\xfc\x18);;)\x03\xe8);;\xfe\xabddd\x01\x90\x02\xdc\x17-(\x15\xfd\x1dd;)d);;)d);\xc8dddd\x00\x00\x00\x03\xff\x9c\x00d\x04\xb0\x04L\x00\x0b\x00#\x001\x00\x00\x002\x16\x15\x11\x14\x06\"&5\x114\x03%#\x13\x16\x06#\"+\x01\"&'\x02=\x01454>\x01;\x01%\x01\x15\".\x03=\x014>\x027\x04i*\x1d\x1d*\x1dd\xfd]&/\x03\x11\x15\x05\x02T\x14\x1d\x047\x02\x0b\x0c\xc8\x02\xa3\xfc\x18\x04\x0e\"\x1a\x16\x15\x1d\x1d\x0b\x04L\x1d\x15\xfc\xae\x15\x1d\x1d\x15\x03R\x15\xfc\x99\xc8\xfe\xec\x10\x08\x1c\x15\x01Q\x0e\xfa\x02\x04\x10\x0f\x0d\xfa\xfe\xd4\xfa\x01\x0b\x13)\x1c2\x1a(\x14\x0c\x01\x00\x00\x00\x02\x00J\x00\x00\x04f\x04\xb0\x00,\x005\x00\x00\x0132\x16\x0f\x01\x1e\x01\x17\x13\x1732\x16\x14\x06\x07\x0e\x04#\".\x04/\x01.\x0146;\x017\x13>\x017'&6\x03\x16327\x0e\x01\"&\x02)^\x14\x12\x06\x12Sz\x0f?v\x11\x13\x1c\x1a\x12\x08\x1edj\x9fO9t\\U>/\x0c\x0b\x12\x1a\x1c\x13\x11v?\x0fzS\x12\x06\x13$2451\x0c7F8\x04\xb0\x15\x13%\x13\x7fM\xfe\xb9\xad\x1d)(\x07\x04\x0b\x1c\x16\x12\n\x0e\x11\x12\x0e\x05\x04\x08()\x1d\xad\x01GM~\x14 \x13\x1a\xfb\xbe\x06\x061==\x00\x01\x00\x14\x00\x14\x04\x9c\x04\x9c\x00\x17\x00\x00\x017\x07\x17\x07\x17\x07\x17'\x07'\x07'\x077'7'7'\x177\x177\x03 \xe0N\xea\xb4\xb4\xeaN\xe0-\x9b\x9b-\xe0N\xea\xb4\xb4\xeaN\xe0-\x9b\x9b\x03\xb2N\xe0-\x9b\x9b-\xe0N\xea\xb4\xb4\xeaN\xe0-\x9b\x9b-\xe0N\xea\xb4\xb4\x00\x03\x00\x00\x00d\x04\xb0\x04\xb0\x00!\x00-\x00=\x00\x00\x0132\x16\x1d\x01\x07!2\x16\x1d\x01\x14\x07\x03\x0e\x01+\x01\"&/\x01#\"&5\x114?\x02>\x01\x17\x0f\x01\x113\x173\x135!75\x0132\x16\x15\x11\x14\x06+\x01\"&5\x1146\x02\x8a2(<\x1c\x01H(<\x1d\xee\x10,\x17\xfa\x07F\x1f\x1f=-7\x14\x91`\x0d1\x1bd\x96d\x88\xd6\xfa\xfe>2\xfdvd\x15\x1d\x1d\x15d\x15\x1d\x1d\x04\xb0Q,\x96}Q,d-\x1d\xfe\xa8\x18!2\x19\x19$'\x01\x90$\x1b\xc4\xc6\x1c(d\xd4\xd5\xfe\x89d\x01w}\xe1\xaf\xfe\xd4\x1d\x15\xfe\x0c\x15\x1d\x1d\x15\x01\xf4\x15\x1d\x00\x00\x00\x00\x03\x00\x00\x00\x00\x04\xb0\x04L\x00 \x000\x00<\x00\x00\x0132\x16\x17\x13\x16\x1d\x01\x14\x06#!\x16\x1d\x01\x14\x06+\x01\"&/\x02&5\x1146;\x016\x0532\x16\x15\x11\x14\x06+\x01\"&5\x1146!\x07#\x11\x1f\x0135'!5\x03\x02X\xfa\x17,\x10\xee\x1d<(\xfe\xb8\x1c<(2\x1b1\x0d`\x91\x147-=|\xfd\xe9d\x15\x1d\x1d\x15d\x15\x1d\x1d\x02_\x88d\x96d22\x01\xc2\xfa\x04L!\x18\xfe\xa8\x1d-d,Qv\x07\x96,Q(\x1c\xc6\xc4\x1b$\x01\x90'$dd\x1d\x15\xfe\x0c\x15\x1d\x1d\x15\x01\xf4\x15\x1dd\xfe\x89\xd5\xd4\xaf\xe1}\x01w\x00\x03\x00\x00\x00d\x05\x0e\x04O\x00\x1b\x007\x00G\x00\x00\x01%6\x1f\x01\x1e\x01\x0f\x01!2\x16\x14\x06+\x01\x03\x0e\x01#!\"&5\x11467\x17\x11\x17!\x13>\x01;\x0126&#!*\x03.\x04'&?\x01'\x0532\x16\x15\x11\x14\x06+\x01\"&5\x1146\x01d\x01k\x1f\x16n\x0d\x01\x0cT\x01.TlnTj\x83\x06\x1b\x0f\xfe\xaa\x07\xa6\x1c\x0e:d\x01%\x83\x06\x1b\x0f\xcb\x15\x13\x12\x16\xfe8\x02\n\x02 \x03\x07\x03\x05\x03\x01\x0c\x11\x92V\xfdOd\x15\x1d\x1d\x15d\x15\x1d\x1d\x03i\xe6\x10\x16p\x0d&\x0fyL\x90N\xfe\xad\x15(\xa2\x0d\x02\x0d\x11%\nH\xfe Y\x01S\x15(22\x01\x02\x02\x03\x05\x02\x19\x16\xb7S\xe4\x1d\x15\xfe\x0c\x15\x1d\x1d\x15\x01\xf4\x15\x1d\x00\x00\x00\x03\xff\x9c\x00d\x04\xb0\x04O\x00\x1d\x006\x00F\x00\x00\x01\x05\x1e\x04\x15\x11\x14\x06#!\"&'\x03#\"&463!'&6?\x016\x07\x17\x16\x07\x0e\x05*\x02#!\x1532\x16\x17\x13!7\x11%\x0532\x16\x15\x11\x14\x06+\x01\"&5\x1146\x01\xdb\x01n\x02\x08\x14\x10\x0d\xac\x07\xfe\xaa\x0f\x1b\x06\x83jUmlT\x01.U\x0b\x01\x0dn\x16J\x92\x11\x0c\x02\x03\x05\x03\x07\x03 \x03\n\x01\xfe%\xdd\x0f\x1c\x06\x82\x01&j\xfe\xaa\x02Pd\x15\x1d\x1d\x15d\x15\x1d\x1d\x04O\xe6\x01\x05\x10\x11\x17\x0b\xfd\xf3\x0d\xa2(\x15\x01SN\x90Ly\x0f&\x0dp\x16\xae\xb7\x16\x19\x02\x05\x03\x02\x02\x01d(\x15\xfe\xadY\x01\xf7\xec\xe4\x1d\x15\xfe\x0c\x15\x1d\x1d\x15\x01\xf4\x15\x1d\x00\x00\x00\x03\x00a\x00\x00\x04L\x05\x0e\x00\x1b\x007\x00G\x00\x00\x002\x16\x1d\x01\x05\x1e\x01\x15\x11\x14\x06#!\"&/\x01\x03&?\x01>\x01\x1f\x01\x114\x1754&\x06\x15\x11\x1c\x03\x0e\x04\x07\x06/\x01\x07\x13!7\x11%.\x01\x03!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x01\xde\x90N\x01S\x15(\xa2\x0d\xfd\xf3\x11%\n \xe6\x10\x16p\x0d&\x0fy\xc622\x01\x02\x02\x03\x05\x02\x19\x16\xb7S\xec\x01\xf7Y\xfe\xad\x15(\x96\x01\xf4\x15\x1d\x1d\x15\xfe\x0c\x15\x1d\x1d\x05\x0enTj\x83\x06\x1b\x0f\xfe\xaa\x07\xa6\x1c\x0e\x0e\x01k\x1f\x16n\x0d\x01\x0cT\x01.T\xd6\xcb\x15\x13\x12\x16\xfe8\x02\n\x02 \x03\x07\x03\x05\x03\x01\x0c\x11\x92V\xfe\xadd\x01%\x83\x06\x1b\xfd\x0b\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\x00\x03\xff\xfd\x00\x06\x03\xe8\x05\x14\x00\x0f\x00-\x00I\x00\x00\x01!26=\x014&#!\"\x06\x1d\x01\x14\x16\x01\x15\x14\x06\"&5\x11\x07\x06&/\x01&7\x13>\x043!2\x16\x15\x11\x14\x06\x07\x01\x03\x1776\x17\x1e\x05\x1c\x02\x15\x11\x14\x166=\x01467%\x11'\x01^\x01\xf4\x15\x1d\x1d\x15\xfe\x0c\x15\x1d\x1d\x01\x0fN\x90Ly\x0f&\x0dp\x16\x10\xe6\x01\x05\x10\x11\x17\x0b\x02\x0d\x0d\xa2(\x15\xfd\x89\xecS\xb7\x16\x19\x02\x05\x03\x02\x02\x0122(\x15\x01SY\x04L\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d\xfc\xe6jTnlT\x01.T\x0c\x01\x0dn\x16\x1f\x01k\x02\x08\x13\x0f\x0c\xa6\x07\xfe\xaa\x0f\x1b\x06\x01\xcf\xfe\xadV\x92\x11\x0c\x01\x03\x05\x03\x07\x03 \x02\n\x02\xfe8\x16\x12\x13\x15\xcb\x0f\x1b\x06\x83\x01%d\x00\x02\x00\x16\x00\x16\x04\x9a\x04\x9a\x00\x0f\x00%\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x01%&\x06\x1d\x01!\"\x06\x1d\x01\x14\x163!\x15\x14\x167%64\x01\xe2\xec\xd6\x9b[[\x9b\xd6\xec\xd6\x9b[[\x9b\x02\x86\xfe\xed\x10\x17\xfe\xed\n\x0f\x0f\n\x01\x13\x17\x10\x01\x13\x10\x04\x9a[\x9b\xd6\xec\xd6\x9b[[\x9b\xd6\xec\xd6\x9b\xfe9\xdf\x0d\n\x15\x89\x0f\n\x96\n\x0f\x89\x15\n\x0d\xdf\x0d&\x00\x00\x02\x00\x16\x00\x16\x04\x9a\x04\x9a\x00\x0f\x00%\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x0d\x01\x06\x14\x17\x05\x166=\x01!26=\x014&#!54&\x01\xe2\xec\xd6\x9b[[\x9b\xd6\xec\xd6\x9b[[\x9b\x01%\xfe\xed\x10\x10\x01\x13\x10\x17\x01\x13\n\x0f\x0f\n\xfe\xed\x17\x04\x9a[\x9b\xd6\xec\xd6\x9b[[\x9b\xd6\xec\xd6\x9b\xe8\xdf\x0d&\x0d\xdf\x0d\n\x15\x89\x0f\n\x96\n\x0f\x89\x15\n\x00\x00\x00\x02\x00\x16\x00\x16\x04\x9a\x04\x9a\x00\x0f\x00%\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x01\x03&\"\x07\x03\x06\x16;\x01\x11\x14\x16;\x01265\x11326\x01\xe2\xec\xd6\x9b[[\x9b\xd6\xec\xd6\x9b[[\x9b\x02K\xdf\x0d&\x0d\xdf\x0d\n\x15\x89\x0f\n\x96\n\x0f\x89\x15\n\x04\x9a[\x9b\xd6\xec\xd6\x9b[[\x9b\xd6\xec\xd6\x9b\xfe@\x01\x13\x10\x10\xfe\xed\x10\x17\xfe\xed\n\x0f\x0f\n\x01\x13\x17\x00\x00\x02\x00\x16\x00\x16\x04\x9a\x04\x9a\x00\x0f\x00%\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x05#\"\x06\x15\x11#\"\x06\x17\x13\x1627\x136&+\x01\x114&\x01\xe2\xec\xd6\x9b[[\x9b\xd6\xec\xd6\x9b[[\x9b\x01\x97\x96\n\x0f\x89\x15\n\x0d\xdf\x0d&\x0d\xdf\x0d\n\x15\x89\x0f\x04\x9a[\x9b\xd6\xec\xd6\x9b[[\x9b\xd6\xec\xd6\x9b\xbb\x0f\n\xfe\xed\x17\x10\xfe\xed\x10\x10\x01\x13\x10\x17\x01\x13\n\x0f\x00\x00\x03\x00\x18\x00\x18\x04\x98\x04\x98\x00\x0f\x00\x96\x00\xa6\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01%\x0e\x03\x07\x06&\x07\x0e\x01\x07\x06\x16\x07\x0e\x01\x07\x06\x16\x07\x14\x16\x072\x1e\x01\x17\x1e\x02\x17\x1e\x027\x16\x0e\x01\x17\x1e\x02\x17\x14\x06\x14\x17\x167>\x027.\x01'.\x01'\"\x0e\x02\x07\x06'&65.\x01'6.\x01\x06\x07\x06'&767\x1e\x02\x17\x1e\x03\x1f\x01>\x02'&>\x017>\x037&72\x16267.\x03'4>\x02&'\x1e\x01?\x016.\x02'\x06\x07\x14\x1e\x01\x15.\x02'>\x017\x162>\x01\x01\xe4\xe8\xd5\x9b\\\\\x9b\xd5\xe8\xd5\x9b\\\\\x9b\x01d\x0f+\x1c:\n\x0f=\x0f\x14?\x03\x03\x13\x01\x031\x05 \x1c\x06\"\x01\x0c\x16\x19\x07\x10\"/\x0b\x15?9\x1d\x07\x14\x19\x03\x0d\x14#\x13\x07\x05hu\x1e!$\x03\x0d0\x0c\x0fE\x11\x12.(,\x103\x0f\x04\x01\x06)\x04\x01\x03\x0b\x1a\x12\x17\x13\x13\x0b\x06\x10\x06(\x1b\x06\x07\x16\x15\x13\x06\x05\x02\x0b\x05\x03\x03\x0d\x17\x04\x06 \x07\x18\x16\x06\x10\x08 \x11\x17 \n*!A\x0b\x04\x02\x01\x03\x03\x1f7\x0b\x0c\x05\x1d,8\x0d\x12!\x10\x12\x08?*\x10\x03\x1a\x03\n\x12\n\x11\x04\x98\\\x9b\xd5\xe8\xd5\x9b\\\\\x9b\xd5\xe8\xd5\x9b\x11\x0c\x11\x07 \x02\x03\x06\x05\x07'\x0f\x0b\x17\x07\"r\x16\"v\x1c G\x18\n\x14\x04\x08\x0e\x10\x04 .\x1e\x04\x0f&*\x11\x15\x1b\x1c\x04\x07\x12\n\x0c\x02r\x1d$> \x08\x01\x07\x07\x10\x0b\x01\x02\x0b\x0b#\x17\x011\x01\x0d \x02\x0f\x1f\x19\x02\x14\x19\x1d\x1c\x1e\x10\x06\x01\x01\x07\n\x0c\x18\x11\x0d\x04\x03\x0c% \x10\x12\x16\x17\x0d\x0e*\x14\x19\n\x12\x12\x03 \x0b\x17'\x14\"\x06\x01\x0e \x0c\x07\x01\x0d\x03\x04\x05\x1c$\x0c\x12\x0b\x04g\x112(\x03\x01 \x0b\x0b\x0b%\x07\n\x0c\x11\x00\x00\x00\x00\x01\x00\x00\x00\x02\x04\xaf\x04\x85\x00\x16\x00\x00\x016\x17\x05\x177\x16\x06\x07\x0e\x01'\x01\x06\"/\x01&47\x01&6\x02\xf4\xa4\x8e\xfe\xfd\x91\xfb\x06PM<\x86;\xfd\xac\x0f+\x0fo\x0f\x0f\x02X\"O\x04\x85\\e\x8a\xe8~Y\x87+\"\x0b\x16\xfd\xac\x10\x10n\x0f+\x10\x02We\xc9\x00\x06\x00\x00\x00`\x04\xb0\x04\xac\x00\x0f\x00\x13\x00#\x00'\x007\x00;\x00\x00\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x05#\x153\x05!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x05!\x15!\x05!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x05!\x15!d\x03\xe8);;)\xfc\x18);;\x04\x11\xc8\xc8\xfc\x18\x03\xe8);;)\xfc\x18);;\x04\x11\xfe\x0c\x01\xf4\xfc\x18\x03\xe8);;)\xfc\x18);;\x04\x11\xfe\xd4\x01,\x04\xac;)d);;)d);dd\xc8;)d);;)d);dd\xc8;)d);;)d);dd\x00\x00\x00\x02\x00d\x00\x00\x04L\x04\xb0\x00\x0b\x00\x11\x00\x00\x13!2\x16\x14\x06#!\"&46\x01\x11\x07\x11\x01!\x96\x03\x84\x15\x1d\x1d\x15\xfc|\x15\x1d\x1d\x02;\xc8\xfe\xa2\x03\x84\x04\xb0\x1d*\x1d\x1d*\x1d\xfdD\xfe\xd4\xc8\x01\xf4\x01\xf4\x00\x00\x00\x03\x00\x00\x00d\x04\xb0\x04\xb0\x00\x17\x00\x1b\x00%\x00\x00\x0132\x16\x1d\x01!2\x16\x15\x11!5#\x15!\x11463!546\x17\x1535\x01\x15\x14\x06#!\"&=\x01\x01\xf4\xc8);\x01,);\xfe\x0c\xc8\xfe\x0c;)\x01,;)\xc8\x01\xf4;)\xfc\x18);\x04\xb0;)d;)\xfepdd\x01\x90);d);ddd\xfdD\xc8);;)\xc8\x00\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x15\x00+\x00A\x00W\x00\x00\x13!2\x16\x0f\x01\x17\x16\x14\x0f\x01\x06\"/\x01\x07\x06&5\x1146)\x012\x16\x15\x11\x14\x06/\x01\x07\x06\"/\x01&4?\x01'&6\x01\x17\x16\x14\x0f\x01\x17\x16\x06#!\"&5\x1146\x1f\x01762\x0576\x16\x15\x11\x14\x06#!\"&?\x01'&4?\x0162\x172\x01,\x15\x08\x0e^\xc7\x07\x07j\x08\x14\x08\xc7^\x0e\x15\x1d\x035\x01,\x15\x1d\x15\x0e^\xc7\x08\x14\x08j\x07\x07\xc7^\x0e\x08\xfe/j\x07\x07\xc7^\x0e\x08\x15\xfe\xd4\x15\x1d\x15\x0e^\xc7\x08\x14\x02\xcb^\x0e\x15\x1d\x15\xfe\xd4\x15\x08\x0e^\xc7\x07\x07j\x08\x14\x08\x04\xb0\x15\x0e^\xc7\x08\x14\x08j\x07\x07\xc7^\x0e\x08\x15\x01,\x15\x1d\x1d\x15\xfe\xd4\x15\x08\x0e^\xc7\x07\x07j\x08\x14\x08\xc7^\x0e\x15\xfd&j\x08\x14\x08\xc7^\x0e\x15\x1d\x15\x01,\x15\x08\x0e^\xc7\x07\xce^\x0e\x08\x15\xfe\xd4\x15\x1d\x15\x0e^\xc7\x08\x14\x08j\x07\x07\x00\x00\x00\x06\x00\x00\x00\x00\x04\xa8\x04\xa8\x00\x0f\x00\x1b\x00#\x00;\x00C\x00K\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&$2\x16\x14\x06\"&4$2\x16\x14\x06#\"'\x07\x16\x15\x14\x06\"&546?\x02&54\x042\x16\x14\x06\"&4$2\x16\x14\x06\"&4\x01\xdb\xf2\xdd\x9f__\x9f\xdd\xf2\xdd\xa0^^\xa0\x01\xc6\xe0\xbfoo\xbf\xe0\xbfoo\xfe-- - \x01L- \x16\x0e\x0f7\x113H3)\x1fz\x01 \xfe\x87- - \x02\x1d- - \x04\xa8_\x9f\xdd\xf2\xdd\xa0^^\xa0\xdd\xf2\xdd\x9fWo\xbf\xe0\xbfoo\xbf\xe0\xbf\x06 -!!- -!\n\x91\x17\x1c$33$ 1\x05~\x01\x0e\x0e\x17\xa4 - - - -\x00\x01\xff\xd8\x00Z\x04\xb9\x04\xbc\x00[\x00\x00%\x01676&'&#\"\x0e\x03\x07\x00\x07\x0e\x04\x17\x1e\x01327\x016'.\x01#\"\x07\x06\x07\x01\x0e\x01&47\x007>\x0132\x17\x1e\x01\x17\x16\x06\x07\x0e\x06\x07\x06#\"&'&67\x0167632\x17\x1e\x01\x17\x16\x06\x07\x01\x0e\x01'.\x01\x02\"\x01\xd5[\x08\x07v_\x16\x19\"A0?! \xfe\x88\x0f\x1e\x1e-\x13\x0d\x05 Y7J3\x02$$\x10\x07\x1d\x12\x1a\x18\x0d\x1a\xfe\xab\x0f)\x1c\x0e\x01G\"#A.\x0e\x0f,=\x0d\x0e\x18#\x0c(wn\x8bkV\x0e8@Fv\"0\x1aD\x01\xffG([kPHNg\x0f\x118B\xfe\x1e\x0f*\x10\x10\x03\xad\x01\xd6[eb\x9b\x11\x04\x14\x1a2!\x1f\xfe\x89\x0f\x1b\x1d5(7\x1d>B3\x02$$'\x10\x14\x17\x0c\x1a\xfe\xae\x0f\x01\x1c)\x0e\x01M\"#!\x01\x087)/c#\x0b*xn\x89fL\x07\x1b@9N\xbeD\x01\xffH\x187!$\x86W]\xb5B\xfe$\x0f\x02\x0f\x0f&\x00\x00\x00\x02\x00d\x00X\x04\xaf\x04D\x00\x19\x00D\x00\x00\x01>\x02\x1e\x02\x15\x14\x0e\x03\x07.\x0454>\x02\x1e\x01\x05\"\x0e\x03\".\x03#\"\x06\x15\x14\x1e\x02\x17\x16\x17\x1e\x042>\x03767>\x0454&\x02\x890{xuX6Cy\x84\xa8>>\xa7\x85xC8Zvxy\x01#!?2-*!')-?\"Co\x1bA23\x0f\x07\x0f:+1!\x0d\"3)@\x0c\x04\x08+)?\x1d\x17j\x03\xb5DH\x05-Sv@9y\x80\x7f\xb2UU\xb2\x7f\x80y9@vS-\x05H-&65&&56&oM\x178J41\x0f\x07\x0e<*.\x18\x180(@\x0b\x04 )*D*2\x13Om\x00\x02\x009\xff\xf2\x04w\x04\xbe\x00\x17\x00.\x00\x00\x002\x1f\x01\x16\x15\x14\x06\x0f\x01&/\x017'\x01\x17\x07/\x01&47\x01\x037\x16\x1f\x01\x16\x14\x07\x01\x06\"/\x01&4?\x01\x16\x1f\x01\x07\x17\x01\x02\xab\xbbB\x8dB8\"\x1d\x1f.\x12_\xf7\xfe{\xd4i\x13\x8dBB\x01\x1b\x12i\n \x8dBB\xfe\xe5B\xbaB\x8dBB7\x1d.\x12_\xf7\x01\x85\x04\xbeB\x8dB^*k\"\x1d5.\x12_\xf8\xfe{\xd4j\x12\x8dB\xbaB\x01\x1b\xfeFi\x08 \x8dB\xbaB\xfe\xe5BB\x8dB\xbbB77/\x11_\xf8\x01\x85\x00\x00\x00\x00\x03\x00\xc8\x00\x00\x03\xe8\x04\xb0\x00\x11\x00\x15\x00\x1d\x00\x00\x002\x1e\x02\x15\x11\x14\x06#!\"&5\x114>\x01\x07\x11!\x11\x00\"\x06\x14\x16264\x02\x06\xaa\x9ad:;)\xfd\xa8);\x02X\xfe\xffV==V=\x04\xb0\x1e.2\x15\xfcG);;)\x03\xb9\x153-\xaa\xfdD\x02\xbc\xfd\x16=V==V\x00\x01\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x16\x00\x00 \x01\x16\x14\x06\"/\x01\x01\x11'\x01\x05\x13\x01'!\x01'&462\x03\x86\x01\x1b\x0f\x1d*\x0e$\xfe\xe9\xd4\xfe\xcc\xfe\xe8\xcb\x013\xd2\x01,\x01\x0b#\x0f\x1d*\x04\xa1\xfe\xe6\x0f*\x1d\x0f#\xfe\xf5\xfe\xd4\xd2\xfe\xcd\xcb\x01\x18\x014\xd4\x01\x17$\x0e*\x1d\x00\x00\x00\x00\x03\x01'\x00\x11\x04 \x04\xe0\x002\x00@\x00K\x00\x00\x01\x15\x1e\x04\x17#.\x03'\x11\x17\x1e\x04\x15\x14\x06\x07\x15#5&'.\x01'3\x1e\x01\x17\x11'.\x0454>\x0275\x19\x01\x0e\x03\x15\x14\x1e\x03\x17\x16\x17\x11>\x044.\x02\x02\xbc&ER<,\x02\x9f\x04\x0d\x1d3'@\"\x8b\xaa\x0cMO\x10W(kVMb\x10\x01O\x08\x0e\x19/9X6FpH*\x06M\xfe\x12\x01\x12\x04\x0e\x1d6&\x1d+\x19\x14\x08\x06\x03\xd0\xfe\xca\x02 \x16 4C4%\x19\x00\x00\x00\x01\x00d\x00f\x03\x94\x04\xad\x00J\x00\x00\x012\x1e\x01\x15#4.\x02#\"\x06\x07\x06\x15\x14\x1e\x01\x17\x16\x173\x15#\x16\x06\x07\x06\x07>\x0136\x16327\x17\x0e\x03#\".\x01\x07\x0e\x01\x0f\x01'>\x057>\x01'#53&'.\x02>\x0176\x021T\x99^\x99'<;\x1a%T\x14)\x1b\x1a\x18\x06\x03\xf1\xc5\x08\x15\x15-6\"b\x16 \x8c\"S52\x1f68\x1c \x17jt&'V\x18\x177\x04\x18\x07\x13\x0c\x11 0\x0c$\xdd\xa6\x17\x15\x07\n\x02\x0e-$a\x04\xadP\x8bN(?\"\x12\x1d\x15,9\x1aJ0* \x05d2\x82\x1e>2\n\x0f\x01\"\x1e\x93\x13\x17\x08\x01\"\x1f\x04\x03\x1a\x0c\x0b\x91\x03\x10\x05\x0d\x0b\x11\n7\x8fGd/9\x14+DAL!X\x00\x00\x00\x02\x00\x19\xff\xff\x04\x97\x04\xb0\x00\x0f\x00\x1f\x00\x00\x0132\x16\x0f\x01\x06\"/\x01&6;\x01\x113\x05\x17\x16\x06+\x01\x11#\x11#\"&?\x0162\x01\x90\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xc8\x02\x17\xe6\x0e\x08\x15\x96\xc8\x96\x15\x08\x0e\xe6\x0e*\x01,\x16\x0e\xfa\x0f\x0f\xfa\x0e\x16\x03\x84\x10\xf9\x0e\x15\xfc|\x03\x84\x15\x0e\xf9\x0f\x00\x00\x04\x00\x19\xff\xff\x03\xe8\x04\xb0\x00\x07\x00\x17\x00\x1b\x00%\x00\x00\x01#5#\x15#\x11!\x0132\x16\x0f\x01\x06\"/\x01&6;\x01\x113\x05\x1535\x13\x073\x15!57#5!\x03\xe8ddd\x01,\xfd\xa8\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xc8\x01\x91dc\xc8\xc8\xfe\xd4\xc8\xc8\x01,\x02\xbcdd\x01\xf4\xfc|\x16\x0e\xfa\x0f\x0f\xfa\x0e\x16\x03\x84d\xc8\xc8\xfd\x12\xfad\x96\xfad\x00\x00\x00\x00\x04\x00\x19\xff\xff\x03\xe8\x04\xb0\x00\x0f\x00\x19\x00!\x00%\x00\x00\x0132\x16\x0f\x01\x06\"/\x01&6;\x01\x113\x05\x073\x15!57#5!\x11#5#\x15#\x11!\x07\x1535\x01\x90\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xc8\x02X\xc8\xc8\xfe\xd4\xc8\xc8\x01,ddd\x01,\xc7d\x01,\x16\x0e\xfa\x0f\x0f\xfa\x0e\x16\x03\x84\x96\xfad\x96\xfad\xfbPdd\x01\xf4d\xc8\xc8\x00\x00\x00\x04\x00\x19\xff\xff\x04L\x04\xb0\x00\x0f\x00\x15\x00\x1b\x00\x1f\x00\x00\x0132\x16\x0f\x01\x06\"/\x01&6;\x01\x113\x01#\x11#53\x13#5#\x11!\x07\x1535\x01\x90\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xc8\x02Xdd\xc8dd\xc8\x01,\xc7d\x01,\x16\x0e\xfa\x0f\x0f\xfa\x0e\x16\x03\x84\xfe\x0c\x01\x90d\xfbPd\x01\x90d\xc8\xc8\x00\x00\x00\x00\x04\x00\x19\xff\xff\x04L\x04\xb0\x00\x0f\x00\x15\x00\x19\x00\x1f\x00\x00\x0132\x16\x0f\x01\x06\"/\x01&6;\x01\x113\x01#5#\x11!\x07\x1535\x03#\x11#53\x01\x90\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xc8\x02\xbcd\xc8\x01,\xc7d\x01dd\xc8\x01,\x16\x0e\xfa\x0f\x0f\xfa\x0e\x16\x03\x84\xfe\x0cd\x01\x90d\xc8\xc8\xfb\xb4\x01\x90d\x00\x00\x00\x00\x05\x00\x19\xff\xff\x04\xb0\x04\xb0\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00\x00\x0132\x16\x0f\x01\x06\"/\x01&6;\x01\x113\x05#53\x13!5!\x13!5!\x13!5!\x01\x90\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xc8\x01\xf4\xc8\xc8d\xfe\xd4\x01,d\xfep\x01\x90d\xfe\x0c\x01\xf4\x01,\x16\x0e\xfa\x0f\x0f\xfa\x0e\x16\x03\x84\xc8\xc8\xfe\x0c\xc8\xfe\x0c\xc8\xfe\x0c\xc8\x00\x05\x00\x19\xff\xff\x04\xb0\x04\xb0\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00\x00\x0132\x16\x0f\x01\x06\"/\x01&6;\x01\x113\x05!5!\x03!5!\x03!5!\x03#53\x01\x90\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xc8\x03 \xfe\x0c\x01\xf4d\xfep\x01\x90d\xfe\xd4\x01,d\xc8\xc8\x01,\x16\x0e\xfa\x0f\x0f\xfa\x0e\x16\x03\x84\xc8\xc8\xfe\x0c\xc8\xfe\x0c\xc8\xfe\x0c\xc8\x00\x02\x00\x00\x00\x00\x04L\x04L\x00\x0f\x00\x1f\x00\x00\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146\x05!\"\x06\x15\x11\x14\x163!265\x114&\x01^\x01\x90\xa2\xbc\xbb\xa3\xfep\xa5\xb9\xb9\x02g\xfe\x0c);;)\x01\xf4);;\x04L\xbb\xa3\xfep\xa5\xb9\xb9\xa5\x01\x90\xa5\xb9\xc8;)\xfe\x0c);;)\x01\xf4);\x00\x00\x00\x00\x03\x00\x00\x00\x00\x04L\x04L\x00\x0f\x00\x1f\x00+\x00\x00\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146\x05!\"\x06\x15\x11\x14\x163!265\x114&\x05\x17\x16\x14\x0f\x01\x06&5\x1146\x01^\x01\x90\xa5\xb9\xb9\xa5\xfep\xa3\xbb\xbc\x02d\xfe\x0c);;)\x01\xf4);;\xfeo\xfd\x11\x11\xfd\x10\x18\x18\x04L\xb9\xa5\xfep\xa5\xb9\xb9\xa5\x01\x90\xa3\xbb\xc8;)\xfe\x0c);;)\x01\xf4);\x82\xbe\x0c$\x0c\xbe\x0c\x0b\x15\x01\x90\x15\x0b\x00\x00\x00\x00\x03\x00\x00\x00\x00\x04L\x04L\x00\x0f\x00\x1f\x00+\x00\x00\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146\x05!\"\x06\x15\x11\x14\x163!265\x114&\x05!2\x16\x0f\x01\x06\"/\x01&6\x01^\x01\x90\xa3\xbb\xb9\xa5\xfep\xa5\xb9\xb9\x02g\xfe\x0c);;)\x01\xf4);;\xfe\x15\x01\x90\x15\x0b\x0c\xbe\x0c$\x0c\xbe\x0c\x0b\x04L\xbc\xa2\xfep\xa5\xb9\xb9\xa5\x01\x90\xa3\xbb\xc8;)\xfe\x0c);;)\x01\xf4);\xc8\x18\x10\xfd\x11\x11\xfd\x10\x18\x00\x00\x00\x03\x00\x00\x00\x00\x04L\x04L\x00\x0f\x00\x1f\x00+\x00\x00\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146\x05!\"\x06\x15\x11\x14\x163!265\x114&\x05\x17\x16\x06#!\"&?\x0162\x01^\x01\x90\xa5\xb9\xb9\xa5\xfep\xa3\xbb\xb9\x02g\xfe\x0c);;)\x01\xf4);;\xfe\xfb\xbe\x0c\x0b\x15\xfep\x15\x0b\x0c\xbe\x0c$\x04L\xb9\xa5\xfep\xa3\xbb\xbc\xa2\x01\x90\xa5\xb9\xc8;)\xfe\x0c);;)\x01\xf4);\xcf\xfd\x10\x18\x18\x10\xfd\x11\x00\x00\x00\x00\x02\x00\x00\x00\x00\x05\x14\x04L\x00\x1f\x005\x00\x00\x01!2\x16\x15\x11\x14\x06#!\"&=\x01463!265\x114&#!\"&=\x0146\x07\x01\x16\x14\x07\x01\x06&=\x01#\"&=\x0146;\x01546\x02&\x01\x90\xa5\xb9\xb9\xa5\xfep\x15\x1d\x1d\x15\x01\xc2);;)\xfe>\x15\x1d\x1d\xbf\x01D\x10\x10\xfe\xbc\x10\x16\xfa\x15\x1d\x1d\x15\xfa\x16\x04L\xb9\xa5\xfep\xa5\xb9\x1d\x15d\x15\x1d;)\x01\xf4);\x1d\x15d\x15\x1d\xe9\xfe\xe4\x0e&\x0e\xfe\xe4\x0e\n\x15\x96\x1d\x15\xc8\x15\x1d\x96\x15\n\x00\x00\x01\x00\xd9\x00\x02\x03\xd7\x04\x9e\x00#\x00\x00\x01\x17\x16\x07\x06\x02\x07%2\x16\x07\"\x08\x01\x07\x06+\x01'&7>\x01?\x01!\"'&76\x006763\x03\x19 \x08\x03\x03\x98\x02\x01,\x18\x11\x0e\x01\xfe\xf7\xfe\xf3\x04\x0c\x0e \x05\x02P''\xfe\xd2\x17\x08\n\x10K\x01\x0d\xbb\x05 \x10\x04\x9e \n\x11\x0b\xfeS\x07\x01#\x12\xfe\xca\xfe\xc5\x05\x0f\x08\x0b\x15 \xe5nn\x13\x15\x14V\x01/\xd3\x06\x10\x00\x00\x00\x02\x00\x00\x00\x00\x04\xfe\x04L\x00\x1f\x005\x00\x00\x01!2\x16\x1d\x01\x14\x06#!\"\x06\x15\x11\x14\x163!2\x16\x1d\x01\x14\x06#!\"&5\x1146\x05\x01\x16\x14\x07\x01\x06&=\x01#\"&=\x0146;\x01546\x01^\x01\x90\x15\x1d\x1d\x15\xfe>);;)\x01\xc2\x15\x1d\x1d\x15\xfep\xa5\xb9\xb9\x02\xf1\x01D\x10\x10\xfe\xbc\x10\x16\xfa\x15\x1d\x1d\x15\xfa\x16\x04L\x1d\x15d\x15\x1d;)\xfe\x0c);\x1d\x15d\x15\x1d\xb9\xa5\x01\x90\xa5\xb9\xe9\xfe\xe4\x0e&\x0e\xfe\xe4\x0e\n\x15\x96\x1d\x15\xc8\x15\x1d\x96\x15\n\x00\x02\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x15\x001\x00\x00\x01!2\x16\x15\x11\x14\x06/\x01\x01\x06\"/\x01&47\x01'&6\x01#\"\x06\x15\x11\x14\x163!26=\x017\x11\x14\x06#!\"&5\x11463!\x02\xee\x01\x90\x15\x1d\x15\x0em\xfe\xc8\x0f)\x0f\x8d\x0f\x0f\x018m\x0e\x08\xfe\xef\x9c);;)\x01\xf4);\xc8\xbb\xa3\xfep\xa5\xb9\xb9\xa5\x01,\x04\xb0\x1d\x15\xfep\x15\x08\x0em\xfe\xc8\x0f\x0f\x8d\x0f)\x0f\x018m\x0e\x15\xfe\xd4;)\xfe\x0c);;)\x94\xc8\xfe\xd6\xa5\xb9\xb9\xa5\x01\x90\xa5\xb9\x00\x00\x03\x00\x0e\x00\x0e\x04\xa2\x04\xa2\x00\x0f\x00\x1b\x00#\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x042\x16\x14\x06\"&4\x01\xe1\xee\xd9\x9d]]\x9d\xd9\xee\xd9\x9d]]\x9d\x01\xc3\xe6\xc2qq\xc2\xe6\xc2qq\xfe{\xa0rr\xa0r\x04\xa2]\x9d\xd9\xee\xd9\x9d]]\x9d\xd9\xee\xd9\x9dGq\xc2\xe6\xc2qq\xc2\xe6\xc2sr\xa0rr\xa0\x00\x00\x03\x00\x00\x00\x00\x04L\x04\xb0\x00\x15\x00\x1f\x00#\x00\x00\x0132\x16\x15\x1132\x16\x07\x01\x06\"'\x01&6;\x01\x1146\x01!2\x16\x1d\x01!546\x05\x1535\x01\xc2\xc8\x15\x1d\xf5\x14\n\x0e\xfe\x81\x0e'\x0d\xfe\x85\x0d \x15\xfa\x1d\xfe\x85\x03\xe8\x15\x1d\xfb\xb4\x1d\x03gd\x04\xb0\x1d\x15\xfe\xa2\x16\x0f\xfeV\x0f\x0f\x01\xaa\x0f\x16\x01^\x15\x1d\xfc|\x1d\x15\xfa\xfa\x15\x1dd22\x00\x00\x00\x03\x00\x00\x00\x00\x04L\x04\xac\x00\x15\x00\x1f\x00#\x00\x00 \x01\x16\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&7\x01>\x01\x01!2\x16\x1d\x01!546\x05\x1535\x02G\x01z\x0e\n\x15\xf4\"\x16\xc8\x14\x18\xfa\x14\x0b\x0e\x01\x7f\x0e'\xfd\xf9\x03\xe8\x15\x1d\xfb\xb4\x1d\x03gd\x04\x9e\xfeM\x0f \xfa\x14\x1e\x1d\x15\xfa!\x0f\x01\xaf\x10\x02\xfc\x7f\x1d\x15\xfa\xfa\x15\x1dd22\x00\x03\x00\x00\x00\x00\x04L\x04K\x00\x14\x00\x1e\x00\"\x00\x00 \x0162\x1f\x01\x16\x14\x07\x01\x06\"'\x01&4?\x0162\x17\x03!2\x16\x1d\x01!546\x05\x1535\x01\x8c\x01q\x07\x15\x07\x8b\x07\x07\xfd\xf3\x07\x15\x07\xfe\xdc\x07\x07\x8b\x08\x15\x07\xd4\x03\xe8\x15\x1d\xfb\xb4\x1d\x03gd\x02\xd3\x01q\x07\x07\x8b\x08\x15\x07\xfd\xf3\x08\x08\x01#\x08\x14\x08\x8b\x07\x07\xfd\xd2\x1d\x15\xfa\xfa\x15\x1dd22\x00\x04\x00\x00\x00\x00\x04L\x04\x9b\x00 \x00\x19\x00#\x00'\x00\x00\x13762\x1f\x01\x07'&4\x0576\x16\x15\x03\x0e\x01#\x05\"&?\x01'7\x01!2\x16\x1d\x01!546\x05\x1535\x87\x8e\x0e*\x0eM\xd4M\x0e\x02\x16\xd2\x0e\x15\x02\x01\x1d\x15\xfd\xab\x15\x08\x0e\xd0\x9a\xd4\xfe=\x03\xe8\x15\x1d\xfb\xb4\x1d\x03gd\x03\xff\x8e\x0e\x0eM\xd4L\x0f*\x9a\xd2\x0e\x08\x15\xfd\xa9\x14\x1e\x01\x15\x0e\xd0\x9b\xd4\xfd:\x1d\x15\xfa\xfa\x15\x1dd22\x00\x00\x00\x04\x00\x00\x00\x00\x04L\x04\xb0\x00\x0f\x00\x19\x00#\x00'\x00\x00\x01\x05\x1e\x01\x15\x13\x14\x06/\x01\x07'7'&6\x13\x07\x06\"/\x01&4?\x01\x01!2\x16\x1d\x01!546\x05\x1535\x01^\x02W\x14\x1e\x01\x15\x0e\xd0\x9b\xd4\x9b\xd2\x0e\x08\xc3L\x0f*\x0e\x8e\x0e\x0eM\xfe\xfa\x03\xe8\x15\x1d\xfb\xb4\x1d\x03gd\x04\xb0\x02\x01\x1d\x15\xfd\xab\x15\x08\x0e\xd0\x9a\xd4\x9a\xd2\x0e\x15\xfdPM\x0e\x0e\x8e\x0e*\x0eM\xfeX\x1d\x15\xfa\xfa\x15\x1dd22\x00\x02\x00\x04\xff\xec\x04\xb0\x04\xaf\x00\x05\x00\x08\x00\x00% \x01\x11! \x01\x15\x01\x04\xb0\xfe\x1d\xfe\xc6\xfeq\x04\xac\xfd3\x02\xabg\x01\x14\xfeq\x01\xa7\x03\x1c\xfc\xf9\xe6\x03\xb9\x00\x00\x00\x00\x02\x00\x00\x00d\x04L\x04\xb0\x00\x15\x00\x19\x00\x00\x01\x11\x14\x06+\x01\x11!\x11#\"&5\x1146;\x01\x11!\x113\x07#53\x04L\x1d\x15\x96\xfdD\x96\x15\x1d\x1d\x15\xfa\x01\xf4d\xc8dd\x03\xe8\xfc\xae\x15\x1d\x01\x90\xfep\x1d\x15\x03\xe8\x14\x1e\xfe\xd4\x01,\xc8\xc8\x00\x00\x03\x00\x00\x00E\x04\xdd\x04\xb0\x00\x16\x00\x1a\x00/\x00\x00\x01\x07\x01'&\"\x0f\x01!\x11#\"&5\x1146;\x01\x11!\x113\x07#53\x01\x17\x16\x14\x07\x01\x06\"/\x01&4?\x0162\x1f\x01\x0162\x04L\x02\xfe\xd5_ \x19 \x95\xfe\xc8\x96\x15\x1d\x1d\x15\xfa\x01\xf4d\xc8dd\x01\xb0j\x07\x07\xfe\\\x08\x14\x08\xca\x08\x08j\x07\x15\x07O\x01)\x07\x15\x03\xe8\x95\xfe\xd5_ \x93\xfep\x1d\x15\x03\xe8\x14\x1e\xfe\xd4\x01,\xc8\xc8\xfd\xcej\x07\x15\x07\xfe[\x07\x07\xcb\x07\x15\x07j\x08\x08O\x01)\x07\x00\x03\x00\x00\x00\x0d\x05\x07\x04\xb0\x00\x16\x00\x1a\x00>\x00\x00\x01\x11\x07'.\x01\x07\x01!\x11#\"&5\x1146;\x01\x11!\x113\x07#53\x01\x17\x16\x14\x0f\x01\x17\x16\x14\x0f\x01\x06\"/\x01\x07\x06\"/\x01&4?\x01'&4?\x0162\x1f\x01762\x04Lg\x86\x0f%\x10\xfe\xf6\xfe\xb7\x96\x15\x1d\x1d\x15\xfa\x01\xf4d\xc8dd\x01\xf6F\x0f\x0f\x83\x83\x0f\x0fF\x0f)\x0f\x83\x83\x0f)\x0fF\x0f\x0f\x83\x83\x0f\x0fF\x0f)\x0f\x83\x83\x0f)\x03\xe8\xfe\xf3g\x86\x0f\x03\x0e\xfe\xf6\xfep\x1d\x15\x03\xe8\x14\x1e\xfe\xd4\x01,\xc8\xc8\xfd\x8cF\x0f)\x0f\x83\x83\x0f)\x0fF\x0f\x0f\x83\x83\x0f\x0fF\x0f)\x0f\x83\x83\x0f)\x0fF\x0f\x0f\x83\x83\x0f\x00\x00\x03\x00\x00\x00\x15\x04\x97\x04\xb0\x00\x15\x00\x19\x00/\x00\x00\x01\x11!\"\x06\x1d\x01!\x11#\"&5\x1146;\x01\x11!\x113\x07#53\x1332\x16\x1d\x0132\x16\x0f\x01\x06\"/\x01&6;\x01546\x04L\xfe\xa2\x15\x1d\xfe\x0c\x96\x15\x1d\x1d\x15\xfa\x01\xf4d\xc8dd\x96d\x15\x1d\x96\x15\x08\x0e\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\x1d\x03\xe8\xfe\xd4\x1d\x15\x96\xfep\x1d\x15\x03\xe8\x14\x1e\xfe\xd4\x01,\xc8\xc8\xfd\xa8\x1d\x15\xfa\x15\x0e\xe6\x0e\x0e\xe6\x0e\x15\xfa\x15\x1d\x00\x00\x00\x00\x03\x00\x00\x00\x00\x04\x97\x04\xb0\x00\x15\x00\x19\x00/\x00\x00\x01\x11'&\"\x07\x01!\x11#\"&5\x1146;\x01\x11!\x113\x07#53\x13\x17\x16\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&?\x0162\x04L\xa5\x0e*\x0e\xfe\xf9\xfen\x96\x15\x1d\x1d\x15\xfa\x01\xf4d\xc8dd\xeb\xe6\x0e\x08\x15\x96\x1d\x15d\x15\x1d\x96\x15\x08\x0e\xe6\x0e*\x03\xe8\xfep\xa5\x0f\x0f\xfe\xf7\xfep\x1d\x15\x03\xe8\x14\x1e\xfe\xd4\x01,\xc8\xc8\xfd\x85\xe5\x0f\x15\xfa\x14\x1e\x1e\x14\xfa\x15\x0f\xe5\x0f\x00\x03\x00\x00\x00\xc8\x04\xb0\x04L\x00 \x00\x13\x00\x17\x00\x00\x13!2\x16\x1d\x01!546\x01\x11\x14\x06#!\"&5\x11\x13\x15!52\x04L\x15\x1d\xfbP\x1d\x04\x93\x1d\x15\xfb\xb4\x15\x1dd\x01\x90\x04L\x1d\x15\x96\x96\x15\x1d\xfe\xd4\xfd\xda\x15\x1d\x1d\x15\x02&\xfe\xd4\xc8\xc8\x00\x00\x06\x00\x03\x00}\x04\xad\x04\x97\x00\x0f\x00\x19\x00\x1d\x00-\x001\x00;\x00\x00\x01\x17\x16\x14\x0f\x01\x06&=\x01!5!546\x01#\"&=\x0146;\x01\x17#53\x0176\x16\x1d\x01!\x15!\x15\x14\x06/\x01&4\x05#5;\x022\x16\x1d\x01\x14\x06+\x01\x03\xa7\xf8\x0e\x0e\xf8\x0e\x15\xfep\x01\x90\x15\xfd/2\x15\x1d\x1d\x152\xc8dd\xfe\x82\xf7\x0e\x15\x01\x90\xfep\x15\x0e\xf7\x0f\x03\x81ddd3\x14\x1d\x1d\x143\x04\x8d\xe6\x0e*\x0e\xe6\x0e\x08\x15\x96\xc8\x96\x15\x08\xfe\x85\x1d\x15d\x15\x1d\xc8\xc8\xfd\xcb\xe6\x0e\x08\x15\x96\xc8\x96\x15\x08\x0e\xe6\x0e*y\xc8\x1d\x15d\x15\x1d\x00\x00\x00\x00\x02\x00d\x00\x00\x04\xb0\x04\xb0\x00\x16\x00Q\x00\x00\x01%6\x16\x15\x11\x14\x06+\x01\"&5\x11.\x045\x1146%2\x16\x1f\x01\x11\x14\x0e\x02\x0f\x01\x11\x14\x06+\x01\"&5\x11.\x045\x114>\x0332\x16\x1f\x01\x113\x11<\x01>\x0232\x16\x1f\x01\x113\x114>\x03\x03^\x01\x14\x19%\x1d\x15\xc8\x15\x1d\x04\x0e\"\x1a\x16%\xfe\xe1\x16\x19\x02\x01\x15\x1d\x1d\x0b\n\x1d\x15\xc8\x15\x1d\x04\x0e\"\x1a\x16\x01\x07\n\x13\x0d\x14\x19\x02\x03d\x05 \x15\x0f\x17\x19\x01\x01d\x01\x05 \x15\x041t\x12\x14\x1f\xfb\xae\x15\x1d\x1d\x15\x01\x8d\x01\x08\x1b\x1f5\x1e\x01g\x1fD\x91\x19\x0c\x0d\xfe>\x1c?1)\x0b\x0b\xfeA\x15\x1d\x1d\x15\x01\xbf\x04\x0f..@\x1c\x01\xc2\x02\x07\x11\x0d\x0b\x19\x0c\x0d\xfe\xa2\x01^\x02\x07\x11\x0d\x0b\x19\x0c\x0d\xfe\xa2\x01^\x02\x07\x11\x0d\x0b\x00\x01\x00d\x00\x00\x04\xb0\x04L\x003\x00\x00\x01\x15\"\x0e\x03\x15\x11\x14\x16\x1f\x01\x15!5265\x11!\x11\x14\x163\x15!52>\x035\x114&/\x015!\x15\"\x06\x15\x11!\x114\x04\xb0\x04\x0e\"\x1a\x162\x19\x19\xfepK\x19\xfe\x0c\x19K\xfep\x04\x0e\"\x1a\x162\x19\x19\x01\x90K\x19\x01\xf4\x19K\x04L8\x01\x05\n\x14\x0e\xfc\x88\x16\x19\x01\x0288\x0d%\x01\x8a\xfev%\x0d88\x01\x05\n\x14\x0e\x03x\x16\x19\x01\x0288\x0d%\xfev\x01\x8a%\x0d8\x00\x00\x00\x06\x00\x00\x00\x00\x04L\x04L\x00\x0c\x00\x1c\x00 \x00$\x00(\x004\x00\x00\x01!2\x16\x1d\x01#\x055'!7!\x05!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x15!5\x01\x055%\x05\x15!5\x05\x15\x14\x06#!\x07!'!73\x02\xa3\x01w\x15\x1di\xfe\xd9\xc8\xfepd\x01w\xfe%\x01,);;)\xfe\xd4);;)\x01,\x02\xbc\xfep\x01\x90\xfc\x18\x01,\x02\xbc\x1d\x15\xfe\x89d\xfe\x89d\x01\x90\xc8i\x03\xe8\x1d\x15\x96bb\xc8d\xc8;)\xfe\x0c);;)\x01\xf4);d\xc8\xc8\xfe\xf7\x85\xa3\x85\xc6\xc8\xc8f\xf8\x15\x1ddd\xc8\x00\x01\x00\x10\x00\x10\x04\x9f\x04\x9f\x00&\x00\x00\x1376\x16\x1f\x01\x16\x06\x0f\x01\x1e\x01\x177>\x01\x1f\x01\x1e\x01\x0f\x01\x06\".\x06'.\x057\x11\xa2\x11.\x0e\x8b\x0e\x06\x11wf\xfc\x8dw\x113\x13\xc0\x13\x07\x11\xa3\x03\x0d.1LOefx;JwF2\x13\x0b\x01\x03\xef\xa2\x11\x06\x13\xc2\x141\x11v\x8e\xfcev\x11\x04\x0e\x88\x0e/\x11\xa2\x01\x04\x08\x15 5Cc;J\x99|sU@\x10\x00\x00\x00\x02\x00\x00\x00\x00\x04\xb0\x04L\x00#\x00A\x00\x00\x002\x1e\x04\x1f\x01\x15\x14\x06/\x01.\x01=\x01& \x07\x15\x14\x06\x0f\x01\x06&=\x01>\x05\x122\x1e\x02\x1f\x01\x15\x01\x1e\x01\x1d\x01\x14\x06#!\"&=\x01467\x0154>\x02\x01\xfc\xb8\xa6ud?, \x1d\x14\xca\x14\x1d\x8d\xfe\xc2\x8d\x1d\x14\xca\x14\x1d\x03\x0d1;ft\xcapR&\x16\x01\x01\x01m\x0e\x15\x1d\x15\xfb\xb4\x15\x1d\x15\x0e\x01m\x02\x16&\x04L\x15!((\"\n\n\xc8\x15\x18\x03\"\x03\"\x15\x92\x18\x18\x92\x15\"\x03\"\x03\x18\x15\xc8\x04\x0d'$+ \xfe\xe4\x13\x1c\x1c\n\n2\xfe\xd1\x0f2\x14\xd4\x15\x1d\x1d\x15\xd4\x142\x0f\x01/2\x04\x0d!\x19\x00\x00\x03\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x0d\x00\x1d\x00'\x00\x00\x01\x07!'\x113\x15353\x15353\x01!2\x16\x14\x06+\x01\x17!7#\"&46\x03!2\x16\x1d\x01!546\x04L\xc8\xfd\xa8\xc8\xc8\xc8\xc8\xc8\xc8\xfc\xae\x02\xbc\x15\x1d\x1d\x15\x0c\x89\xfcJ\x89\x0c\x15\x1d\x1d\xb3\x04L\x15\x1d\xfbP\x1d\x02\xbc\xc8\xc8\x01\xf4\xc8\xc8\xc8\xc8\xfc\xe0\x1d*\x1ddd\x1d*\x1d\xfe\xd4\x1d\x1522\x15\x1d\x00\x00\x00\x03\x00d\x00\x00\x04\xb0\x04L\x00 \x00\x13\x00\x1d\x00\x00\x01#\"\x06\x15\x11!\x114&\x01#\"\x06\x15\x11!\x114&\x01!\x1146;\x012\x16\x15\x02\xbcd);\x01,;\x01gd);\x01,;\xfd\x1b\xfe\xd4;)d);\x04L;)\xfc\x18\x03\xe8);\xfe\xd4;)\xfdD\x02\xbc);\xfc\xe0\x01\x90);;)\x00\x00\x00\x00\x05\xff\x9c\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00\x1f\x00%\x00)\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x05#\x153\x11!535#\x11!\x05\x11\x07#\x113\x07\x113\x11\xc8\x02\xbc|\xb0\xb0|\xfdD|\xb0\xb0\x18\x03\x84\xfe\x0c\xc8\xc8\xfe\xd4\xc8\xc8\x01,\x01\x90d\xc8\xc8dd\x04L\xb0|\xfe\x0c|\xb0\xb0|\x01\xf4|\xb0\xc8\xfdD\x02\xbc\xc8d\xfe\xd4dd\x01,d\xfe\xd4d\x01\xf4d\xfe\xd4\x01,\x00\x00\x00\x05\xff\x9c\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00\x1f\x00%\x00)\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x01#5#\x15#\x113\x15353\x05\x11\x07#\x113\x07\x113\x11\xc8\x02\xbc|\xb0\xb0|\xfdD|\xb0\xb0\x18\x03\x84\xfe\x0cdddddd\x01\x90d\xc8\xc8dd\x04L\xb0|\xfe\x0c|\xb0\xb0|\x01\xf4|\xb0\xc8\xfdD\x02\xbc\xfd\xa8\xc8\xc8\x01\xf4\xc8\xc8d\xfe\xd4d\x01\xf4d\xfe\xd4\x01,\x00\x04\xff\x9c\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00\x1b\x00#\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x05#\x113\x15!\x11!\x05#\x113\x15!\x11!\xc8\x02\xbc|\xb0\xb0|\xfdD|\xb0\xb0\x18\x03\x84\xfe\x0c\xc8\xc8\xfe\xd4\x01,\x01\x90\xc8\xc8\xfe\xd4\x01,\x04L\xb0|\xfe\x0c|\xb0\xb0|\x01\xf4|\xb0\xc8\xfdD\x02\xbc\xc8\xfe\xd4d\x01\xf4d\xfe\xd4d\x01\xf4\x00\x00\x00\x04\xff\x9c\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00\x16\x00\x19\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x01-\x01\x0d\x01\x11\xc8\x02\xbc|\xb0\xb0|\xfdD|\xb0\xb0\x18\x03\x84\xfe\x0c\xfe\xd4\x01,\x01\x90\xfe\xd4\x04L\xb0|\xfe\x0c|\xb0\xb0|\x01\xf4|\xb0\xc8\xfdD\x02\xbc\xfe\x0c\x96\x96\x96\x96\x01,\x00\x00\x00\x05\xff\x9c\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00\x17\x00 \x00)\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x03!\x11!\x07#\"\x06\x15\x14\x16;\x01\x01\x1132654&#\xc8\x02\xbc|\xb0\xb0|\xfdD|\xb0\xb0\x18\x03\x84d\xfdD\x02\xbcd\x82&96)\x82\xfe\x0c\x82)69&\x04L\xb0|\xfe\x0c|\xb0\xb0|\x01\xf4|\xb0\xc8\xfdD\x02\xbc\xfd\xa8\x01\xf4dVAAT\x01,\xfe\xd4TAAV\x00\x00\x00\x05\xff\x9c\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00\x1f\x00%\x00)\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x05#\x153\x11!535#\x11!\x01#\x11#53\x03#53\xc8\x02\xbc|\xb0\xb0|\xfdD|\xb0\xb0\x18\x03\x84\xfe\x0c\xc8\xc8\xfe\xd4\xc8\xc8\x01,\x01\x90dd\xc8\xc8dd\x04L\xb0|\xfe\x0c|\xb0\xb0|\x01\xf4|\xb0\xc8\xfdD\x02\xbc\xc8d\xfe\xd4dd\x01,\xfe\x0c\x01\x90d\xfe\x0cd\x00\x06\xff\x9c\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00\x19\x00\x1f\x00#\x00'\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x053\x11!\x113\x01#\x11#53\x05\x1535\x01#53\xc8\x02\xbc|\xb0\xb0|\xfdD|\xb0\xb0\x18\x03\x84\xfdD\xc8\xfe\xd4d\x02Xdd\xc8\xfd\xa8d\x01,dd\x04L\xb0|\xfe\x0c|\xb0\xb0|\x01\xf4|\xb0\xc8\xfdD\x02\xbc\xc8\xfep\x01\xf4\xfe\x0c\x01\x90d\xc8\xc8\xc8\xfe\xd4d\x00\x05\xff\x9c\x00\x00\x04\xb0\x04L\x00\x0f\x00\x13\x00\x1c\x00\"\x00&\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x01\x07#575#5!\x01#\x11#53\x03#53\xc8\x02\xbc|\xb0\xb0|\xfdD|\xb0\xb0\x18\x03\x84\xfe\x0c\xc7d\xc7\xc8\x01,\x01\x90dd\xc8\xc7dd\x04L\xb0|\xfe\x0c|\xb0\xb0|\x01\xf4|\xb0\xc8\xfdD\x02\xbc\xfep\xc82\xc8\x96d\xfe\x0c\x01\x90d\xfe\x0cd\x00\x00\x00\x03\x00 \x00 \x04\xa7\x04\xa7\x00\x0f\x00\x1b\x00%\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x07!\x15!\x15!'57!\x01\xe0\xf0\xdb\x9e^^\x9e\xdb\xf0\xdb\x9e^^\x9e\x01\xc5\xe4\xc2qq\xc2\xe4\xc2qql\xfe\xd4\x01,\xfe\xd4dd\x01,\x04\xa7^\x9e\xdb\xf0\xdb\x9e^^\x9e\xdb\xf0\xdb\x9eLq\xc2\xe4\xc2qq\xc2\xe4\xc2\xd0\xc8dd\xc8d\x00\x00\x00\x00\x04\x00 \x00 \x04\xa7\x04\xa7\x00\x0f\x00\x1b\x00'\x00+\x00\x00\x002\x1e\x02\x14\x0e\x02\".\x024>\x01\x04\"\x0e\x01\x14\x1e\x012>\x014&\x07\x15\x07\x17\x15#'#\x15#\x11!\x07\x1535\x01\xe0\xf0\xdb\x9e^^\x9e\xdb\xf0\xdb\x9e^^\x9e\x01\xc5\xe4\xc2qq\xc2\xe4\xc2qql2ddd\x96d\x01,\xc8\xc8\x04\xa7^\x9e\xdb\xf0\xdb\x9e^^\x9e\xdb\xf0\xdb\x9eLq\xc2\xe4\xc2qq\xc2\xe4\xc2\xd0d2d2dd\x01\x90ddd\x00\x00\x02\xff\xf2\xff\x9d\x04\xc2\x04A\x00 \x006\x00\x00\x012\x16\x17632\x16\x14\x06+\x0154&#!\"\x06\x1d\x01#\"&5467&54>\x01\x1332\x16\x15\x1132\x16\x0f\x01\x06\"/\x01&6;\x01\x1146\x01\xf7n\xb5,,.x\xaa\xaax\x80\x1d\x15\xfe\xd4\x15\x1d\xdePpVA\x02b\xaaz\x96\n\x0f\x89\x15\n\x0d\xdf\x0d&\x0d\xdf\x0d\n\x15\x89\x0f\x04Awa\x0e\xad\xf1\xad\xfa\x15\x1d\x1d\x15\xfasOEk\x0e\x13\x12d\xaab\xfd\xb3\x0f\n\xfe\xed\x17\x10\xf4\x10\x10\xf4\x10\x17\x01\x13\n\x0f\x00\x00\x00\x00\x02\xff\xf2\xff\x9c\x04\xc3\x04A\x00\x1c\x003\x00\x00\x012\x16\x17632\x16\x17\x14\x06\x07\x01&\"\x07\x01#\"&5467&54>\x01\x13\x17\x16\x06+\x01\x11\x14\x06+\x01\"&5\x11#\"&76762\x01\xf6n\xb6,+.y\xaa\x01xZ\xfe\x86\x0d%\x0d\xfe\x83 OqVA\x02b\xa9\xe6\xdf\x0d\n\x15\x89\x0f\n\x96\n\x0f\x89\x15\n\x0d\xc7\x18\x13\x19\x04Awa\x0f\xadxc\xa4\x1c\x01h\x10\x10\xfe\x93sOEk\x0e\x13\x13d\xa9c\xfd\x92\xe4\x10\x17\xfe\xed\n\x0f\x0f\n\x01\x13\x17\x10\xcc\x18\x13\x00\x00\x00\x01\x00d\x00\x00\x04L\x04m\x00\x18\x00\x00%5!\x013\x013 \x013\x013\x01!\x15#\"\x06\x1d\x01!54&#\x02\xbc\x01\x90\xfe\xf2\xaa\xfe\xf2\xaa\xfe\xd4\xfe\xd4\xaa\xfe\xf2\xaa\xfe\xf2\x01\x902\x15\x1d\x01\x90\x1d\x15dd\x01,\x01,\x01M\xfe\xb3\xfe\xd4\xfe\xd4d\x1d\x1522\x15\x1d\x00\x00\x00\x00\x01\x00y\x00\x00\x047\x04\x9b\x00/\x00\x00\x012\x16\x17\x1e\x01\x15\x14\x06\x07\x16\x15\x14\x06#\"'\x152\x16\x1d\x01!54635\x06#\"&547.\x0154632\x174&546\x02X^\x93\x1aY{;2 iJ7-\x15\x1d\xfe\xd4\x1d\x15-7Ji\x04/9iJ\x05\x12\x02\xa3\x04\x9bqY\x06\x83Z=g\x1f\x1d\x1aJi\x1e\xfb\x1d\x1522\x15\x1d\xfb\x1eiJ\x12\x14\x15X5Ji\x02\x02\x10\x05t\xa3\x00\x00\x00\x06\x00'\x00\x14\x04\x89\x04\x9c\x00\x11\x00*\x00B\x00J\x00b\x00{\x00\x00\x01\x16\x12\x02\x07\x0e\x01\"&'&\x02\x127>\x012\x16\x05\"\x07\x0e\x01\x07\x06\x16\x1f\x01\x163276767>\x01/\x01&'&\x17\"\x07\x0e\x01\x07\x06\x16\x1f\x01\x16327>\x017>\x01/\x01&'&\x16&\"\x06\x14\x16267\"\x07\x0e\x01\x07\x0e\x01\x1f\x01\x16\x17\x16327>\x0176&/\x01&\x17\"\x07\x06\x07\x06\x07\x0e\x01\x1f\x01\x16\x17\x16327>\x0176&/\x01&\x03\xf2oOOoS\xd9\xdc\xd9SoOOoS\xd9\xdc\xd9\xfe=\x04\x04y\xb1\"\x04\x0d\x0c$\x03\x04\x17\x06\x1bGF`\x0b\x0d\x03 \x03\x0b\x07\x1c\x04\x05Pu\x18\x04\x0c\x0d\"\x04\x04\x16\x06\x12Q9\x0c\x0c\x03 \x03\x0b\x07\xf9c\x8ccc\x8ccV\x16\x06\x12Q:\x0b\x0c\x03 \x03\x0b\x07\x08\x04\x05Pu\x18\x04\x0d\x0c\"\x04\x8d\x17\x06\x1bGF`\x0b\x0d\x03 \x03\x0b\x07\x08\x04\x04y\xb1\"\x04\x0d\x0c$\x03\x03\xf2o\xfe\xd5\xfe\xd5oSWWSo\x01+\x01+oSWW\x1c\x01\"\xb1y\x0c\x16\x03 \x01\x16`FG\x1b\x03\x15\x0c#\x0d\x06\x04\x91\x02\x18uP\x0d\x16\x03 \x01\x15:Q\x12\x03\x15\x0b#\x0c\x07\x04\xfacc\x8ccc\x15\x15:Q\x11\x04\x15\x0b#\x0c\x07\x04\x02\x18uP\x0d\x16\x03 \x01$\x16`FG\x1b\x03\x15\x0c#\x0d\x06\x04\x01\"\xb1y\x0c\x16\x03 \x01\x00\x00\x00\x05\x00d\x00\x00\x03\xe8\x04\xb0\x00\x0c\x00\x0f\x00\x16\x00\x1c\x00\"\x00\x00\x01!\x11#5!\x15!\x11463!\x01#5\x033\x07'353\x03!\"&5\x11\x05\x15\x14\x06+\x01\x02\xbc\x01,\xb4\xfe\xac\xfe\x84\x0f\n\x02?\x01,\xc8d\xa2\xd4\xd4\xa2d\xb4\xfeu\n\x0f\x03\x84\x0f\n\xc3\x03 \xfe\x84\xc8\xc8\x02\xf3\n\x0f\xfe\xd4\xc8\xfc\xe0\xd4\xd4\xc8\xfe\x0c\x0f\n\x01\x8b\xc8\xc3\n\x0f\x00\x00\x00\x00\x05\x00d\x00\x00\x03\xe8\x04\xb0\x00 \x00\x0c\x00\x13\x00\x1a\x00!\x00\x00\x01!\x11 \x01\x11463!\x01#5\x13#\x15#5#7\x03!\"&=\x01)\x01\x15\x14\x06+\x015\x02\xbc\x01,\xfe\xa2\xfd\xda\x0f\n\x02?\x01,\xc8>\xa2d\xa2\xd4\xaa\xfe\x9d\n\x0f\x01|\x02\x08\x0f\n\x9b\x03 \xfd\xf8\x01^\xfd\xda\x04G\n\x0f\xfe\xd4\xc8\xfc|\xc8\xc8\xd4\xfed\x0f\n77\n\x0fP\x00\x00\x00\x00\x03\x00\x00\x00\x00\x04\xb0\x03\xf4\x00\x08\x00\x19\x00\x1f\x00\x00\x01#\x153\x17!\x11#7\x0532\x1e\x02\x15!\x15!\x03\x1134>\x02\x013\x03!\x01!\x04\x8a\xa2dd\xfe\xd4\xa2\xd4\xfd\x12\xc8\x1b\x1a!\x0e\x01,\xfd\xa8\xc8d\x0e!\x1a\x02s\xf0\xf0\xfc\xe0\x01,\x01\xf4\x03 \xc8d\x01,\xd4\xd4\x04\x11+$d\xfe\xa2\x01\xc2$+\x11\x04\xfep\xfep\x01\xf4\x00\x00\x00\x03\x00\x00\x00\x00\x04L\x04L\x00\x19\x002\x009\x00\x00\x0132\x16\x1d\x0132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01546\x0552\x16\x15\x11\x14\x06#!\"'7\x01\x11463\x15\x14\x163!26\x01\x075#535\x02\x8ad\x15\x1d2\x15\x1d\x1d\x15\xfe\xd4\x15\x1d\x1d\x152\x1d\x01s);;)\xfd\xa8\x01\x13\xf6\xfe\xba;)X>\x01,>X\xfd\xb4\xd4\xc8\xc8\x04L\x1d\x152\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d2\x15\x1d\xfa\x96;)\xfc\xe0);\x04\xf6\x01F\x01D);\x96>XX\xfd\xe6\xd4\xa2d\xa2\x00\x03\x00d\x00\x00\x04\xbc\x04L\x00\x19\x006\x00=\x00\x00\x0132\x16\x1d\x0132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01546\x0552\x16\x15\x11#\x113\x14\x0e\x02#!\"&5\x11463\x15\x14\x163!26\x01\x075#535\x01\xc2d\x15\x1d2\x15\x1d\x1d\x15\xfe\xd4\x15\x1d\x1d\x152\x1d\x01s);\xc8\xc8\x0e!\x1a\x1b\xfd\xa8);;)X>\x01,>X\x01\x9c\xd4\xc8\xc8\x04L\x1d\x152\x1d\x15d\x15\x1d\x1d\x15d\x15\x1d2\x15\x1d\xfa\x96;)\xfe\x0c\xfe\xd4$+\x11\x04;)\x03 );\x96>XX\xfd\xe6\xd4\xa2d\xa2\x00\x00\x00\x03\xff\xa2\x00\x00\x05\x16\x04\xd4\x00\x0b\x00\x1b\x00\x1f\x00\x00 \x01\x16\x06#!\"&7\x0162\x13#\"\x06\x17\x13\x1e\x01;\x01267\x136&\x03\x1535\x02\x92\x02}\x17 ,\xfb\x04, \x17\x02}\x16@D\xd0\x14\x18\x04:\x04#\x146\x14#\x04:\x04\x18\xe0\xc8\x04\xad\xfb\xb0&77&\x04P'\xfeL\x1d\x14\xfe\xd2\x14\x1d\x1d\x14\x01.\x14\x1d\xfe\x0cdd\x00\x00\x00\x00 \x00\x00\x00\x00\x04L\x04L\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\x7f\x00\x8f\x00\x00\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x1332\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x0132\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146!32\x16\x1d\x01\x14\x06+\x01\"&=\x0146\x01\xa9\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\x01\x9a\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\xfc\xea\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\x01\x9a\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\x01\x9a\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\xfc\xea\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\x01\x9a\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\x01\x9a\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\x04L\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\xfe\xd4\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\xfe\xd4\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\xfe\xd4\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x00\x00\x00\x03\x00\x00\x00\x00\x04\xb0\x05\x14\x00\x19\x00)\x003\x00\x00\x013\x15#\x15!2\x16\x0f\x01\x06\x07!&/\x01&63!5#5353\x01!2\x16\x14\x06+\x01\x17!7#\"&46\x03!2\x16\x1d\x01!546\x02\xbcdd\x01^>1\x1cB)(\xfc\xfc()B\x1c1>\x01^dd\xc8\xfe>\x02\xbc\x15\x1d\x1d\x15\x0c\x89\xfcJ\x8a\x0d\x15\x1d\x1d\xb3\x04L\x15\x1d\xfbP\x1d\x04\xb0\xc8dO7\x84S33S\x847Od\xc8d\xfc|\x1d*\x1ddd\x1d*\x1d\xfe\xd4\x1d\x1522\x15\x1d\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x05\x14\x00\x05\x00\x19\x00+\x005\x00\x00\x002\x16\x15#4\x07!\x16\x15\x14\x07!2\x16\x0f\x01!'&63!&54\x03!2\x16\x14\x06+\x01\x15\x05!%5#\"&46\x03!2\x16\x1d\x01!546\x020P9\xc2<\x01:\x12\x03\x01H)\x07\"\xaf\xfdZ\xb2\"\n)\x01H\x03\xaf\x02\xbc\x15\x1d\x1d\x15\x96\x01\x13\xfcJ\x01\x13\x96\x15\x1d\x1d\xb3\x04L\x15\x1d\xfbP\x1d\x05\x14;))\x8d%&\x08\x11!\x16\x91\x91\x16!\x11\x08&\xfe\x95\x1d*\x1d\xc8\xc8\xc8\xc8\x1d*\x1d\xfd\xa8\x1d\x1522\x15\x1d\x00\x04\x00\x00\x00\x00\x04\xb0\x04\x9d\x00\x07\x00\x14\x00$\x00.\x00\x00\x002\x16\x14\x06\"&4\x1332\x16\x15\x14\x17!65463\x01!2\x16\x14\x06+\x01\x17!7#\"&46\x03!2\x16\x1d\x01!546\x02\x0d\x96jj\x96j\xb7.\"+'\xfe\xbc'+#\xfe\xcd\x02\xbc\x15\x1d\x1d\x15\x0d\x8a\xfcJ\x89\x0c\x15\x1d\x1d\xb3\x04L\x15\x1d\xfbP\x1d\x04\x9dj\x96jj\x96\xfe\xeb9:LkkL:9\xfer\x1d*\x1ddd\x1d*\x1d\xfe\xd4\x1d\x1522\x15\x1d\x00\x04\x00\x00\x00\x00\x04\xb0\x05\x14\x00\x0f\x00\x1c\x00,\x006\x00\x00\x012\x1e\x01\x15\x14\x06\"&547\x177'6\x1332\x16\x15\x14\x17!65463\x01!2\x16\x14\x06+\x01\x17!7#\"&46\x03!2\x16\x1d\x01!546\x02X/[3o\x9co\"\x90o\xa3\"\x1f.\"+'\xfe\xbc'+#\xfe\xcd\x02\xbc\x15\x1d\x1d\x15\x0d\x8a\xfcJ\x89\x0c\x15\x1d\x1d\xb3\x04L\x15\x1d\xfbP\x1d\x05\x14k\x8b6NooN>Q\x8fo\xa3\x1a\xfe\n9:LkkL:9\xfer\x1d*\x1ddd\x1d*\x1d\xfe\xd4\x1d\x1522\x15\x1d\x00\x00\x00\x03\x00\x00\x00\x00\x04\xb0\x05\x12\x00\x12\x00\"\x00,\x00\x00\x01\x05\x15!\x14\x1e\x03\x17!.\x0154>\x027\x01!2\x16\x14\x06+\x01\x17!7#\"&46\x03!2\x16\x1d\x01!546\x02X\x01,\xfe\xd4%??M\x13\xfd\xee<=Bm\x8fJ\xfe\xa2\x02\xbc\x15\x1d\x1d\x15\x0d\x8a\xfcJ\x89\x0c\x15\x1d\x1d\xb3\x04L\x15\x1d\xfbP\x1d\x04\xb0\xa1\x8b9fQ?H\x19S\xbdTT\xa1vK\x04\xfc~\x1d*\x1ddd\x1d*\x1d\xfe\xd4\x1d\x1522\x15\x1d\x00\x02\x00\xc8\x00\x00\x03\xe8\x05\x14\x00\x0f\x00)\x00\x00\x002\x16\x1d\x01\x1e\x01\x1d\x01!546754\x03!2\x16\x17#\x153\x15#\x153\x15#\x153\x14\x06#!\"&5\x1146\x02/R;.6\xfep6.d\x01\x906\\\x1a\xac\xc8\xc8\xc8\xc8\xc8uS\xfepSuu\x05\x14;)N\x1a\\6226\\\x1aN)\xfeG6.dddddSuuS\x01\x90Su\x00\x00\x03\x00d\xff\xff\x04L\x04L\x00\x0f\x00/\x003\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x03!2\x16\x1d\x01\x14\x06#!\x17\x16\x14\x06\"/\x01!\x07\x06\"&4?\x01!\"&=\x0146\x05\x07!'\x96\x03\x84\x15\x1d\x1d\x15\xfc|\x15\x1d\x1d\x04\x03\xb6\n\x0f\x0f\n\xfe\xe5\xe0\x0d\x1a%\x0dX\xfd\xf4W\x0d&\x1a\x0d\xe0\xfe\xdf\n\x0f\x0f\x01\xaad\x01Dd\x04L\x1d\x15\xfe\x0c\x15\x1d\x1d\x15\x01\xf4\x15\x1d\xfdD\x0f\n2\n\x0f\xe0\x0d%\x1b\x0dXX\x0d\x1b%\x0d\xe0\x0f\n2\n\x0fddd\x00\x00\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04L\x00\x19\x00#\x00-\x007\x00\x00\x13!2\x16\x1d\x01#4&+\x01\"\x06\x15#4&+\x01\"\x06\x15#546\x03!2\x16\x15\x11!\x1146\x13\x15\x14\x06+\x01\"&=\x01!\x15\x14\x06+\x01\"&=\x01\xc8\x03 Sud;)\xfa);d;)\xfa);du\x11\x03\xe8);\xfbP;\xf1\x1d\x15d\x15\x1d\x03\xe8\x1d\x15d\x15\x1d\x04LuS\xc8);;));;)\xc8Su\xfe\x0c;)\xfe\xd4\x01,);\xfe\x0c2\x15\x1d\x1d\x1522\x15\x1d\x1d\x152\x00\x03\x00\x01\x00\x00\x04\xa9\x04\xac\x00\x0d\x00\x11\x00\x1b\x00\x00 \x01\x16\x14\x0f\x01!\x01&47\x0162 \x03\x03!2\x16\x1d\x01!546\x01\xe0\x02\xaa\x1f\x1f\x83\xfe\x1f\xfd\xfb \x01'\x1fY\xfe\xac\x01V\x01/\xfe\xab\xa2\x03 \x15\x1d\xfc|\x1d\x04\x8d\xfdU\x1fY\x1f\x83\x02\x06\x1fY\x1f\x01(\x1f\xfen\xfe\xaa\x010\x01U\xfc\x1b\x1d\x1522\x15\x1d\x00\x00\x00\x00\x02\x00\x8f\x00\x00\x04!\x04\xb0\x00\x17\x00/\x00\x00\x01\x03.\x01#!\"\x06\x07\x03\x06\x163!\x15\x14\x1626=\x01326\x03!546;\x01546;\x01\x113\x1132\x16\x1d\x0132\x16\x15\x04!\xbd\x08'\x15\xfep\x15'\x08\xbd\x08\x13\x15\x02q\x1d*\x1d}\x15\x13\xa8\xfd\xad\x1d\x152\x1d\x150\xc8/\x15\x1d2\x15\x1d\x02\x87\x01\xfa\x13\x1c\x1c\x13\xfe\x06\x13\x1c\x96\x15\x1d\x1d\x15\x96\x1c\xfd\x8c2\x15\x1d2\x15\x1d\x01,\xfe\xd4\x1d\x152\x1d\x15\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x0d\x00\x10\x00\x1f\x00\"\x00\x00\x01!\x11\x14\x06#!\x11\x015463!\x01#5\x01!\x11\x14\x06#!\"&5\x11463!\x01#5\x03\x84\x01,\x0f\n\xfe\x89\xfe\xd4\x0f\n\x01w\x01,\xc8\xfd\xa8\x01,\x0f\n\xfdv\n\x0f\x0f\n\x01w\x01,\xc8\x03 \xfd\xc1\n\x0f\x02O\x01,T\n\x0f\xfe\xd4\xc8\xfe\x0c\xfd\xc1\n\x0f\x0f\n\x03\xb6\n\x0f\xfe\xd4\xc8\x00\x02\xff\x9c\x00d\x05\x14\x04G\x00F\x00V\x00\x00\x0132\x1e\x02\x17\x16\x17\x16676'&7>\x01\x16\x17\x16\x07\x0e\x01+\x01\x0e\x01\x0f\x01\x0e\x01+\x01\"&?\x01\x06+\x01\"'\x07\x0e\x01+\x01\"&?\x01&/\x01.\x01=\x0146;\x0167'&6;\x016\x05#\"\x06\x1d\x01\x14\x16;\x0126=\x014&\x01\xe4\xc3K\x8ejI\x0c\x12\x11\x1fC\n\n\x19\x13\n\x05\x0f\x17\x0c)\x02\x03V=>\x078\x1c'\x03\"\x15d\x15\x18\x03\x0c1*\xc3\x18)\x0b\x03\"\x15d\x15\x18\x03\x1aT,\x9f\x13\x1c\x1d\x15|\x0b-o\x10\x07\x15\xcbt\x01E\xfa\n\x0f\x0f\n\xfa\n\x0f\x0f\x04GAk\x8aI\x0e\x06\n! \"%\x1b\x10\x08\x06\x08\x0c,=?W7|&\xea\x14\x1d\x1d\x14F\x0e\x08@\x14\x1d\x1d\x14\x9dJe5\x07&\x152\x15\x1dWO_\x0e\x13e_\x0f\n2\n\x0f\x0f\n2\n\x0f\x00\x06\xff\x9c\xff\xe6\x05\x14\x04~\x00 \x00$\x004\x00<\x00R\x00b\x00\x00\x01%6\x16\x1f\x01\x16\x06\x0f\x01%32\x16\x1f\x01!2\x16\x1d\x01\x14\x06\x07\x05\x06&'&#!\"&=\x0146\x17#\"\x06\x1d\x01\x14;\x012654&'&\x04\"\x06\x14\x16264\x017>\x01\x1e\x01\x17\x1e\x01?\x01\x17\x16\x06\x0f\x01\x06&/\x01&6%\x07\x06\x1f\x01\x1e\x01?\x016'.\x01'.\x01\x02\x81\x01\xa7\x13.\x0e \x0e\x03\x10\x8b\xfc+jCH\x1ef\x037\x15\x1d\x1c\x13\xfd\x1f\x17\" *:\xfe\xd4>XX\xb9P\x13\x12*\x86\x10\x0b \x0b\x12\x01\x80@--@-\xfe\x0f\x98\x12 \x1e\x13\x10\x1c-\x1a?0\x0d!3P/|)\x82( \x01)f\x1f!%\x0d\x1d\x11=\x13\x05\x02\x14\x07\x0b\x10\x03\x84\xf7\x08\x0b\x10&\x0f*\x0dx\xc8\"6\xd4\x1d\x152\x15&\x07\x84\x04\x14\x0fCX>\xc8>X\xac\x1c\x1583\x10\x10\x0bD\x11\x1c\xc9-@--@\xfe\xdb\x82\x13\n\x11\x12\x13# \x03\x05\xb3=I+E( /\x97/}\x1cX\x1b&+\x0f \x0b5\x10!\x14H \x0c\x04\x00\x00\x00\x00\x03\x00d\x00\x00\x049\x04\xb0\x00Q\x00`\x00o\x00\x00\x0132\x16\x1d\x01\x1e\x01\x17\x16\x0e\x02\x0f\x012\x1e\x05\x15\x14\x0e\x05#\x15\x14\x06+\x01\"&=\x01#\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x01\x11#\"&=\x0146;\x01546;\x012\x16\x1d\x013546\x03\x15!2>\x02574.\x03#\x01\x15!2>\x02574.\x03#\x02q\x96\n\x0fOh\x01\x01 ..\x10\x11\x06\x1240:*\x1d\x17\"6-@#\x1a\x0f\n\x96\n\x0fd\x0f\n\x96\n\x0f\xaf\n\x0f\x0f\nKK\n\x0f\x0f\n\xaf\x0f\n\x96\n\x0fd\x0f\xd7\x01\x07\x1c)\x13\x0b\x01\x01\x0b\x13)\x1c\xfe\xf9\x01k\x1c)\x13\x0b\x01\x01\x0b\x13)\x1c\x04\xb0\x0f\nm!mJ.M-\x1f\x06\x06\x03\x0f\x14(2N-;]<*\x15\x0b\x02K\n\x0f\x0f\nKK\n\x0f\x0f\nK\x0f\n\x96\n\x0f\x02X\x0f\n\x96\n\x0fK\n\x0f\x0f\nKK\n\x0f\xfe\xd4\xc8\x15\x1d\x1d\x0b\n\x04\x0e\"\x1a\x16\xfep\xc8\x15\x1d\x1d\x0b\n\x04\x0e\"\x1a\x16\x00\x00\x03\x00\x04\x00\x02\x04\xb0\x04\xae\x00\x17\x00)\x00,\x00\x00\x13!2\x16\x15\x11\x14\x06\x0f\x01\x0e\x01#!\"&'.\x025\x1146\x04\"\x0e\x04\x0f\x01\x17!7.\x05\x03#\x13\xd4\x03\x0cVz$\x12\x12\x1d\x81R\xfd\xc4R\x82\x1c\x08\x18(z\x02 \x8c}VG+\x1d\x06\x06\x9c\x020\x9c\x02\x08 )IU!\x9d\xc3\x04\xaezV\xfe`3\xb7BBWwvX\x1cZ\xc53\x01\xa0Vz\x99\x17&--%\x0c\x0c\xf3\xf3\x05\x0f,(1#\xfe\xc2\x01\x05\x00\x02\x00\xc8\x00\x00\x03\x84\x05\x14\x00\x0f\x00\x19\x00\x00\x0132\x16\x15\x11\x14\x06#!\"&5\x1146\x01\x15\x14\x06+\x01\"&=\x01\x01\xdb\x96g\xacT)\xfe>)T\xac\x01H6\x15\x96\x156\x05\x14\xacg\xfe\x0c)TT)\x01\xf4g\xac\xfc\x18\xe1\x1566\x15\xe1\x00\x00\x02\x00\xc8\x00\x00\x03\x84\x05\x14\x00\x0f\x00\x19\x00\x00\x013\x14\x163\x11\x14\x06#!\"&5\x1146\x01\x15\x14\x06+\x01\"&=\x01\x01\xdb`\xb3\x96T)\xfe>)T\xac\x01H6\x15\x96\x156\x05\x14\x96\xb3\xfeB)TT)\x01\xf4g\xac\xfc\x18\xe1\x1566\x15\xe1\x00\x00\x02\x00\x00\x00\x14\x05\x0e\x04\x1a\x00\x14\x00\x1a\x00\x00 \x01%\x07\x15\x17\x15'\x075754&>\x02?\x01' \x01\x05%5\x05%\x05\x0e\xfd\x82\xfe\x86Nd\x96\x96d\x01\x01\x01\x05\x04/\x93\x02\x82\x01\\\xfe\xa2\xfe\xa2\x01^\x01^\x02\xff\xfe\xe5\xaa<\xe0\x96\xc7\x94\x95\xc8\x96\xfa\x04\x0d\x06\n\x06\x03(A\x01\x1b\xfdb\xa6\xa6\x93\xa5\xa5\x00\x00\x03\x00d\x01\xf4\x04\xb0\x03 \x00\x07\x00\x0f\x00\x17\x00\x00\x122\x16\x14\x06\"&4$2\x16\x14\x06\"&4$2\x16\x14\x06\"&4\xbc|XX|X\x01\xe8|XX|X\x01\xe8|XX|X\x03 X|XX|XX|XX|XX|XX|\x00\x00\x00\x00\x03\x01\x90\x00\x00\x02\xbc\x04L\x00\x07\x00\x0f\x00\x17\x00\x00\x002\x16\x14\x06\"&4\x122\x16\x14\x06\"&4\x122\x16\x14\x06\"&4\x01\xe8|XX|XX|XX|XX|XX|X\x04LX|XX|\xfe\xc8X|XX|\xfe\xc8X|XX|\x00\x00\x00\x03\x00d\x00d\x04L\x04L\x00\x0f\x00\x1f\x00/\x00\x00\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146\x13!2\x16\x1d\x01\x14\x06#!\"&=\x0146}\x03\xb6\n\x0f\x0f\n\xfcJ\n\x0f\x0f\n\x03\xb6\n\x0f\x0f\n\xfcJ\n\x0f\x0f\n\x03\xb6\n\x0f\x0f\n\xfcJ\n\x0f\x0f\x04L\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\xfep\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\xfep\x0f\n\x96\n\x0f\x0f\n\x96\n\x0f\x00\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x0f\x00\x1f\x00/\x003\x00\x00\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146\x05!\"\x06\x15\x11\x14\x163!265\x114&\x05!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x15!5\x01^\x01\xf4\xa2\xbc\xbb\xa3\xfe\x0c\xa5\xb9\xb9\x02\xcb\xfd\xa8);;)\x02X);;\xfd\xb1\x01\xf4\x15\x1d\x1d\x15\xfe\x0c\x15\x1d\x1dG\x01\x90\x04\xb0\xbb\xa3\xfe\x0c\xa5\xb9\xb9\xa5\x01\xf4\xa5\xb9\xc8;)\xfd\xa8);;)\x02X);d\x1d\x15\xfe\xd4\x15\x1d\x1d\x15\x01,\x15\x1dd\xc8\xc8\x00\x00\x00\x00\x01\x00d\x00d\x04\xb0\x04L\x00;\x00\x00\x13!2\x16\x14\x06+\x01\x1532\x16\x14\x06+\x01\x1532\x16\x14\x06+\x01\x1532\x16\x14\x06#!\"&46;\x015#\"&46;\x015#\"&46;\x015#\"&46\x96\x03\xe8\x15\x1d\x1d\x1522\x15\x1d\x1d\x1522\x15\x1d\x1d\x1522\x15\x1d\x1d\x15\xfc\x18\x15\x1d\x1d\x1522\x15\x1d\x1d\x1522\x15\x1d\x1d\x1522\x15\x1d\x1d\x04L\x1d*\x1d\xc8\x1d*\x1d\xc8\x1d*\x1d\xc8\x1d*\x1d\x1d*\x1d\xc8\x1d*\x1d\xc8\x1d*\x1d\xc8\x1d*\x1d\x00\x00\x00\x06\x01,\x00\x05\x03\xe8\x04\xa3\x00\x07\x00\x0d\x00\x13\x00\x19\x00\x1f\x00*\x00\x00\x01\x1e\x01\x06\x07.\x016\x012\x16\x15\"&%\x14\x06#46\x012\x16\x15\"&%\x14\x06#46\x03\x15\x14\x06\"&=\x01\x1632\x02\x8aW??WW??\xfe\xf9|\xb0|\xb0\x02\xbc\xb0|\xb0\xfd\xc0|\xb0|\xb0\x02\xbc\xb0|\xb0\xb0\x1d*\x1d(\x03\x11\x04\xa3C\xb2\xb2BB\xb2\xb2\xfe\xc0\xb0|\xb0||\xb0|\xb0\xfe\xd4\xb0|\xb0||\xb0|\xb0\xfe\xd3\x90\x15\x1d\x1d\x15\x8e\x04\x00\x00\x01\xff\xb5\x00\xc8\x04\x94\x03\x81\x00B\x00\x00\x0176\x17\x01\x1e\x01\x07\x0e\x01+\x012\x15\x14\x0e\x04+\x01\"\x1147&\"\x07\x16\x15\x10+\x01\".\x03543#\"&'&67\x016\x1f\x01\x1e\x01\x0e\x01/\x01\x07!'\x07\x06.\x016\x02\xe9E\x19\x14\x01*\x0b\x08\x06\x05\x1a\x0f\x08\x01\x04\x0d\x1b'?)\x92\xb8\n\x14T\x15\x0b\xb8\x8e0I'\x19\x07\x02\x07\x0f\x19\x06\x06\x08\x0b\x01*\x14\x1aL\x14\x15\n#\x143\xb6\x03{\xb6,\x14#\n\x16\x03n\x13\x06\x12\xfe\xd9\x0b\x1f\x0f\x0e\x13\x0d\x1d6F82\x1c\x01 \x18\x17\x04\x04\x18\x17\xfe\xe0*\x035\x11#\"\x0e\x05\x15#\x11!\x01#4.\x03+\x01\x11\x14\x16\x173\x15#525\x11#\"\x0e\x03\x15#5!\x04\xb02\x08\x0b\x19\x13&\x18\x19\xc82\x19\x19\xfep\x04\x0e\"\x1a\x16\xc8\x19\x18&\x13\x19\x0b\x082\x03\xe8\xfdD\x19\x08\n\x18\x10\x11d\x19\x0d\x0c\xc82d\x11\x10\x18\n\x08\x19\x01\xf4\x03\x84\x15 \x15\x0e\x08\x03\x01\xfc\xae\x16\x19\x01\x02dd\x01\x05 \x15\x0e\x03R\x01\x03\x08\x0e\x15 \x15\x01,\xfd\x12\x0f\x13\n\x05\x01\xfeW\x0b\x0d\x0122\x19\x01\xa9\x01\x05\n\x13\x0f\x96\x00\x00\x00\x00\x03\x00\x00\x00\x00\x04L\x04\xae\x00\x1d\x00 \x000\x00\x00\x015\"'.\x01/\x01\x01#\x01\x06\x07\x0e\x01\x0f\x01\x15!5\"&?\x01!\x17\x16\x06#\x15\x01\x1b\x01\x01\x15\x14\x06#!\"&=\x01463!2\x16\x03\xe8\x19\x1e\x0e\x16\x05\x04\xfe\xdfE\xfe\xd4\x12\x15 \x1f\x0b\x0b\x01\x111;\x12E\x01%=\x0d!'\xfe\xec\x86y\x01\xb1\x1d\x15\xfc\x18\x15\x1d\x1d\x15\x03\xe8\x15\x1d\x01,2 \x0e\"\n\x0b\x02\xeb\xfd\x0e#\x15 \x13\x05\x0522+.\xb0\xa6\"A2\x01\x87\x01V\xfe\xaa\xfd\xe3d\x15\x1d\x1d\x15d\x15\x1d\x1d\x00\x03\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x0f\x00G\x00J\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x05#\"\x07\x01\x06\x07\x06\x07\x06\x1d\x01\x14\x163!26=\x014&#\"'&?\x01!\x17\x16\x07\x06#\"\x06\x1d\x01\x14\x163!26=\x014&'\"'&'#\x01&\x13#\x132\x04L\x15\x1d\x1d\x15\xfb\xb4\x15\x1d\x1d\x02FF\x0d\x05\xfe\xd5\x11\x12\x12&\x0c\x0b \x01\x11\x08\x0c\x0c\x087\x10\n\n?\x01\n9\x0b\x11\x0c\x18\x08\x0c\x0c\x08\x019\x08\x0c\x0b\x08\x11\x19\x19\x0f\x01\xfe\xe0\x05\x0e\xc5g\x04\xb0\x1d\x15\xfb\xb4\x15\x1d\x1d\x15\x04L\x15\x1dR\x0c\xfd\x0f \x13\x12\x10\x05\x0d2\x08\x0c\x0c\x082\x08\x0c\x17\x0e\x19\xa3\x99\x1f\x18\x11\x0c\x082\x08\x0c\x0c\x082\x07\x0c\x01\x19\x1b$\x02\xec\x0c\xfe\x05\x01\x08\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x03\x00\x13\x00#\x00'\x00\x00\x01!5!\x05!2\x16\x15\x11\x14\x06#!\"&5\x1146)\x012\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x04\xb0\xfbP\x04\xb0\xfb\x82\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\x02m\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1dG\x01,\x04Ld\xc8\x1d\x15\xfc|\x15\x1d\x1d\x15\x03\x84\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1dd\xfe\xd4\x01,\x00\x04\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x0f\x00\x1f\x00#\x00'\x00\x00\x13!2\x16\x15\x11\x14\x06#!\"&5\x1146\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x13!5!2\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1d\x02m\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1dG\x01,\xc8\xfbP\x04\xb0\x04\xb0\x1d\x15\xfc|\x15\x1d\x1d\x15\x03\x84\x15\x1d\xfe\x0c\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1dd\xfe\xd4\x01,\xfd\xa8d\x00\x00\x00\x00\x02\x00\x00\x00d\x04\xb0\x03\xe8\x00'\x00+\x00\x00\x13!2\x16\x15\x1135463!2\x16\x1d\x013\x15#\x15\x14\x06#!\"&=\x01#\x11\x14\x06#!\"&5\x1146\x01\x11!\x112\x01\x90\x15\x1dd\x1d\x15\x01\x90\x15\x1ddd\x1d\x15\xfep\x15\x1dd\x1d\x15\xfep\x15\x1d\x1d\x02\x9f\x01,\x03\xe8\x1d\x15\xfe\xa2\x96\x15\x1d\x1d\x15\x96d\x96\x15\x1d\x1d\x15\x96\xfe\xa2\x15\x1d\x1d\x15\x03 \x15\x1d\xfe\xd4\xfe\xd4\x01,\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x03\x00\x13\x00\x17\x00'\x00\x003#\x113\x17!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146ddd\x96\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1dG\x01,\xfe\xa2\x03\x84\x15\x1d\x1d\x15\xfc|\x15\x1d\x1d\x04\xb0d\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1dd\xfe\xd4\x01,\xfe\x0c\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1d\x00\x00\x00\x00\x02\x00d\x00\x00\x04L\x04\xb0\x00'\x00+\x00\x00\x0132\x16\x15\x11\x14\x06+\x01\x15!2\x16\x15\x11\x14\x06#!\"&5\x11463!5#\"&5\x1146;\x0153\x07\x11!\x11\x02X\x96\x15\x1d\x1d\x15\x96\x01\xc2\x15\x1d\x1d\x15\xfc|\x15\x1d\x1d\x15\x01^\x96\x15\x1d\x1d\x15\x96d\xc8\x01,\x04L\x1d\x15\xfep\x15\x1dd\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1dd\x1d\x15\x01\x90\x15\x1dd\xc8\xfe\xd4\x01,\x00\x00\x00\x04\x00\x00\x00\x00\x04\xb0\x04\xb0\x00\x03\x00\x13\x00\x17\x00'\x00\x00!#\x113\x05!2\x16\x15\x11\x14\x06#!\"&5\x1146\x17\x11!\x11\x01!2\x16\x15\x11\x14\x06#!\"&5\x1146\x04\xb0dd\xfdv\x01\x90\x15\x1d\x1d\x15\xfep\x15\x1d\x1dG\x01,\xfc\xae\x03\x84\x15\x1d\x1d\x15\xfc|\x15\x1d\x1d\x04\xb0d\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1dd\xfe\xd4\x01,\xfe\x0c\x1d\x15\xfep\x15\x1d\x1d\x15\x01\x90\x15\x1d\x00\x00\x01\x01,\x000\x03o\x04\x80\x00\x0f\x00\x00 \x01\x06#\"&5\x114632\x17\x01\x16\x14\x03a\xfe\x12\x17\x12\x0e\x10\x10\x0e\x12\x17\x01\xee\x0e\x025\xfe\x12\x17\x1b\x19\x03\xe8\x19\x1b\x17\xfe\x12\x0e*\x00\x00\x00\x00\x01\x01A\x002\x03\x84\x04~\x00\x0b\x00\x00 \x016\x16\x15\x11\x14\x06'\x01&4\x01O\x01\xee\x1d**\x1d\xfe\x12\x0e\x02{\x01\xee\x1d\x11)\xfc\x18)\x11\x1d\x01\xee\x0e*\x00\x00\x00\x00\x01\x002\x01A\x04~\x03\x84\x00\x0b\x00\x00\x13!2\x16\x07\x01\x06\"'\x01&6d\x03\xe8)\x11\x1d\xfe\x12\x0e*\x0e\xfe\x12\x1d\x11\x03\x84*\x1d\xfe\x12\x0e\x0e\x01\xee\x1d*\x00\x00\x00\x00\x01\x002\x01,\x04~\x03o\x00\x0b\x00\x00 \x01\x16\x06#!\"&7\x0162\x02{\x01\xee\x1d\x11)\xfc\x18)\x11\x1d\x01\xee\x0e*\x03a\xfe\x12\x1d**\x1d\x01\xee\x0e\x00\x00\x00\x00\x02\x00\x08\x00\x00\x04\xb0\x04(\x00\x06\x00\n\x00\x00\x01\x15\x015-\x015\x01!5!\x02\xbc\xfdL\x01\x9d\xfec\x04\xa8\xfc\xe0\x03 \x02\xe5\xb6\xfe\xbd\xdd\xc1\xc1\xdd\xfb\xd8\xc8\x00\x00\x00\x00\x02\x00\x00\x00d\x04\xb0\x04\xb0\x00\x0b\x001\x00\x00\x01#\x153\x15!\x1135#5!\x0134>\x05;\x01\x11\x14\x06\x0f\x01\x15!5\".\x035\x1132\x1e\x05\x153\x11!\x04\xb0\xc8\xc8\xfe\xd4\xc8\xc8\x01,\xfbP2\x08\x0b\x19\x13&\x18\x19d2\x19\x19\x01\x90\x04\x0e\"\x1a\x16d\x19\x18&\x13\x19\x0b\x082\xfc\xe0\x03\x84dd\x01,dd\xfe\x0c\x15 \x15\x0e\x08\x03\x01\xfd\xda\x16\x19\x01\x02dd\x01\x05 \x15\x0e\x02&\x01\x03\x08\x0e\x15 \x15\x01,\x00\x00\x02\x00\x00\x00\x00\x04L\x03\xe8\x00%\x001\x00\x00\x01#4.\x05+\x01\x11\x14\x16\x1f\x01\x15!52>\x035\x11#\"\x0e\x05\x15#\x11!\x01#\x153\x15!\x1135#5!\x03 2\x08\x0b\x19\x13&\x18\x19d2\x19\x19\xfep\x04\x0e\"\x1a\x16d\x19\x18&\x13\x19\x0b\x082\x03 \x01,\xc8\xc8\xfe\xd4\xc8\xc8\x01,\x02\xbc\x15 \x15\x0e\x08\x03\x01\xfd\xda\x16\x19\x02\x01dd\x01\x05 \x15\x0e\x02&\x01\x03\x08\x0e\x15 \x15\x01,\xfc\xe0dd\x01,dd\x00\x00\x01\x00\xc8\x00f\x03r\x04J\x00\x12\x00\x00\x0132\x16\x07 \x01\x16\x06+\x01\"'\x01&47\x016\x02\xbd\xa0\x10\n\x0c\xfe0\x01\xd0\x0c\n\x10\xa0\x0d\n\xfe)\x07\x07\x01\xd7\n\x04J\x16\x0c\xfe0\xfe0\x0c\x16 \x01\xd7\x08\x14\x08\x01\xd7 \x00\x00\x01\x01>\x00f\x03\xe8\x04J\x00\x12\x00\x00\x0132\x17\x01\x16\x14\x07\x01\x06+\x01\"&7 \x01&6\x01S\xa0\x0d\n\x01\xd7\x07\x07\xfe)\n\x0d\xa0\x10\n\x0c\x01\xd0\xfe0\x0c\n\x04J \xfe)\x08\x14\x08\xfe) \x16\x0c\x01\xd0\x01\xd0\x0c\x16\x00\x00\x01\x00f\x00\xc8\x04J\x03r\x00\x12\x00\x00\x00\x16\x1d\x01\x14\x07\x01\x06\"'\x01&=\x0146\x17 \x01\x044\x16 \xfe)\x08\x14\x08\xfe) \x16\x0c\x01\xd0\x01\xd0\x03w\n\x10\xa0\x0d\n\xfe)\x07\x07\x01\xd7\n\x0d\xa0\x10\n\x0c\xfe0\x01\xd0\x00\x00\x00\x01\x00f\x01>\x04J\x03\xe8\x00\x12\x00\x00 \x01\x16\x1d\x01\x14\x06' \x01\x06&=\x0147\x0162\x02j\x01\xd7 \x16\x0c\xfe0\xfe0\x0c\x16 \x01\xd7\x08\x14\x03\xe1\xfe)\n\x0d\xa0\x10\n\x0c\x01\xd0\xfe0\x0c\n\x10\xa0\x0d\n\x01\xd7\x07\x00\x00\x00\x02\x00\xd9\xff\xf9\x04=\x04\xb0\x00\x05\x00:\x00\x00\x01\x14\x06#46\x0532\x16\x1f\x0167>\x02\x1e\x04\x06\x07\x0e\x06\x07\x06\"&#\"\x06\"'.\x03/\x01.\x01>\x04\x1e\x01\x17'&6\x03\xe8\xb0|\xb0\xfeVd\x15&\x07O\x05\x0b\"(P3G*+\x0f\x05\x11\x01\x04\x12\x17*3M,\x0d:I\x0b\x0eG7\x109_7&\x07\x07\x0f\x06\x0f%*>7F1\x1f\x93\x0c\x0d\x04\xb0|\xb0|\xb0\xc8\x1c\x13\xc2\x01\x02\x06\x07\x07\x05\x0f\x1f5KmC\x07\x19KG\\JB\x11\x05\x05\x07\x07\x19ktl$#?hI7 \x13\x07\x03\x06\x05\xc0\x12\x18\x00\x00\x00\x00\x02\x00\xc8\x00\x15\x03\x84\x04\xb0\x00\x16\x00\x1a\x00\x00\x13!2\x16\x15\x11\x14\x06+\x01\x11\x07\x06&5\x11#\"&5\x1146\x17\x15!5\xfa\x02X\x15\x1d\x1d\x15\x96\xff\x13\x1a\x96\x15\x1d\x1d\xab\x01,\x04\xb0\x1d\x15\xfep\x15\x1d\xfe\x0c\xb2 \x10\x15\x02\x8a\x1d\x15\x01\x90\x15\x1dddd\x00\x00\x00\x02\x00\xc8\x00\x19\x04L\x04\xb0\x00\x0e\x00\x12\x00\x00\x13!2\x16\x15\x11\x05\x11%!\x11#\x1146\x01\x1575\xfa\x02\xee'=\xfdD\x02X\xfdDd\x1f\x01\x0dd\x04\xb0Q,\xfc[u\x03\xb6}\xfc\x18\x04\x01\x174\xfd]d\x14d\x00\x01\x00\x00\x00\x01\x02Mo\xc3\x04__\x0f<\xf5\x00\x1f\x04\xb0\x00\x00\x00\x00\xd0vs\x97\x00\x00\x00\x00\xd0vs\x97\xffQ\xff\x9c\x05\xdc\x05\x14\x00\x00\x00\x08\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x05\x14\xff\x85\x00\x00\x05\x14\xffQ\xfe\xd4\x05\xdc\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa3\x01\xb8\x00(\x00\x00\x00\x00\x01\x90\x00\x00\x04\xb0\x00\x00\x04\xb0\x00d\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00p\x02\x8a\x00\x00\x05\x14\x00\x00\x02\x8a\x00\x00\x05\x14\x00\x00\x01\xb1\x00\x00\x01E\x00\x00\x00\xd8\x00\x00\x00\xd8\x00\x00\x00\xa2\x00\x00\x01\x04\x00\x00\x00H\x00\x00\x01\x04\x00\x00\x01E\x00\x00\x04\xb0\x00d\x04\xb0\x00{\x04\xb0\x00\xc8\x04\xb0\x00\xc8\x01\xf4\x00\x00\x04\xb0\xff\xf2\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\xff\xf0\x04\xb0\x00\x00\x04\xb0\x00\x0e\x04\xb0\x00 \x04\xb0\x00d\x04\xb0\xff\xd3\x04\xb0\xff\xd3\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00&\x04\xb0\x00n\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00d\x04\xb0\x00\x1a\x04\xb0\x00d\x04\xb0\x00\x0c\x04\xb0\x00d\x04\xb0\x00\x17\x04\xb0\xff\x9c\x04\xb0\x00d\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x00\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00d\x04\xb0\x00\x00\x04\xb0\x00d\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00d\x04\xb0\x00\xc8\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x005\x04\xb0\x00d\x04\xb0\x00\xc8\x04\xb0\xff\xb5\x04\xb0\x00!\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\xff\x9c\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\xdb\x04\xb0\x00\x17\x04\xb0\x00u\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\n\x04\xb0\x00\xc8\x04\xb0\x00\x00\x04\xb0\x00\x9d\x04\xb0\x00\xc8\x04\xb0\x00\xc8\x04\xb0\x00\xc8\x04\xb0\x00\x00\x04\xb0\xff\xfe\x04\xb0\x01,\x04\xb0\x00d\x04\xb0\x00\x88\x04\xb0\x01;\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x00\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x17\x04\xb0\x00\x00\x04\xb0\x00\xb7\x04\xb0\x00\xb7\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00I\x04\xb0\x00\x17\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00]\x04\xb0\xff\xdc\x04\xb0\xff\xdc\x04\xb0\xff\x9f\x04\xb0\x00d\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00d\x04\xb0\xff\xff\x04\xb0\x00\x00\x04\xb0\xffQ\x04\xb0\x00\x06\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x01E\x04\xb0\x00\x01\x04\xb0\x00\x00\x04\xb0\xff\x9c\x04\xb0\x00J\x04\xb0\x00\x14\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\x00\x00\x04\xb0\xff\x9c\x04\xb0\x00a\x04\xb0\xff\xfd\x04\xb0\x00\x16\x04\xb0\x00\x16\x04\xb0\x00\x16\x04\xb0\x00\x16\x04\xb0\x00\x18\x04\xb0\x00\x00\x04\xc4\x00\x00\x04\xb0\x00d\x00\x00\x00\x00\x00\x00\xff\xd8\x00d\x009\x00\xc8\x00\x00\x01'\x00d\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd9\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00d\x00d\x00\x00\x00\x10\x00\x00\x00\x00\x00d\xff\x9c\xff\x9c\xff\x9c\xff\x9c\xff\x9c\xff\x9c\xff\x9c\xff\x9c\x00 \x00 \xff\xf2\xff\xf2\x00d\x00y\x00'\x00d\x00d\x00\x00\x00\x00\x00d\xff\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8\x00d\x00\x00\x00\x01\x00\x8f\x00\x00\xff\x9c\xff\x9c\x00d\x00\x04\x00\xc8\x00\xc8\x00\x00\x00d\x01\x90\x00d\x00\x00\x00d\x01,\xff\xb5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x01,\x01A\x002\x002\x00\x08\x00\x00\x00\x00\x00\xc8\x01>\x00f\x00f\x00\xd9\x00\xc8\x00\xc8\x00\x00\x00*\x00*\x00*\x00*\x00\xb2\x00\xe8\x00\xe8\x01N\x01N\x01N\x01N\x01N\x01N\x01N\x01N\x01N\x01N\x01N\x01N\x01N\x01N\x01\xa4\x02\x06\x02\"\x02~\x02\x86\x02\xac\x02\xe4\x03F\x03n\x03\x8c\x03\xc4\x04\x08\x042\x04b\x04\xa2\x04\xdc\x05\\\x05\xba\x06r\x06\xf4\x07 \x07b\x07\xca\x08\x1e\x08b\x08\xbe 6 \x84 \xb6 \xde\n(\nL\n\x94\n\xe2\x0b0\x0b\x8a\x0b\xca\x0c\x08\x0cX\x0d*\x0d^\x0d\xb0\x0e\x0e\x0eh\x0e\xb4\x0f(\x0f\xa6\x0f\xe6\x10\x12\x10T\x10\x90\x10\xaa\x11*\x11v\x11\xb6\x12\n\x128\x12|\x12\xc0\x13\x1a\x13t\x13\xd0\x14*\x14\xd4\x15<\x15\xa8\x15\xcc\x16\x04\x166\x16`\x16\xb0\x16\xfe\x17R\x17\xa6\x18\x02\x18.\x18j\x18\x96\x18\xb0\x18\xe0\x18\xfe\x19(\x19h\x19\x94\x19\xc4\x19\xda\x19\xee\x1a6\x1ah\x1a\xb8\x1a\xf6\x1b^\x1b\xb4\x1c2\x1c\x94\x1c\xe2\x1d\x1c\x1dD\x1dl\x1d\x94\x1d\xbc\x1d\xe6\x1e.\x1ev\x1e\xc0\x1fb\x1f\xd2 F \xbe!2!v!\xb8\"@\"\x96\"\xb8#\x0e#\"#8#z#\xc2#\xe0$\x02$0$^$\x96$\xe2%4%`%\xbc&\x14&~&\xe6'P'\xbc'\xf8(4(p(\xac)\xa0)\xcc*&*J*\x84+\n+z,\x08,h,\xba,\xec-\x1c-\x88-\xf4.(.f.\xa2.\xd8/\x0e/F/~/\xb2/\xf80>0\x840\xd21\x121`1\xae1\xe82$2^2\x9a2\xde3\"3>3h3\xb64\x184`4\xa84\xd25,5\x9e5\xe86>6|6\xdc7\x1a7N7\x927\xd48\x108B8\x868\xc89\n9J9\x889\xcc:\x1c:l:\x9a:\xde;\xa0;\xdc<\x18:>\x8c>\xd4?(?n?\xaa?\xfa@H@\x80@\xc6A\x02A~B\x18B\xa8B\xeeC\x18CBCvC\xa0C\xcaD\x10D`D\xaeD\xf6EZE\xb6F\x06FtF\xb4F\xf6G6GvG\xb6G\xf6H\x16H2HNHjH\x86H\xccI\x12I8I^I\x84I\xaaJ\x02J.JR\x00\x01\x00\x00\x01\x17\x00\xa7\x00\x11\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x01\x00\x00\x00@\x00.\x00\x00\x00\x00\x00\x00\x00\x10\x00\xc6\x00\x01\x00\x00\x00\x00\x00\x13\x00\x12\x00\x00\x00\x03\x00\x01\x04 \x00\x00\x00j\x00\x12\x00\x03\x00\x01\x04 \x00\x01\x00(\x00|\x00\x03\x00\x01\x04 \x00\x02\x00\x0e\x00\xa4\x00\x03\x00\x01\x04 \x00\x03\x00L\x00\xb2\x00\x03\x00\x01\x04 \x00\x04\x008\x00\xfe\x00\x03\x00\x01\x04 \x00\x05\x00x\x016\x00\x03\x00\x01\x04 \x00\x06\x006\x01\xae\x00\x03\x00\x01\x04 \x00\x08\x00\x16\x01\xe4\x00\x03\x00\x01\x04 \x00 \x00\x16\x01\xfa\x00\x03\x00\x01\x04 \x00\x0b\x00$\x02\x10\x00\x03\x00\x01\x04 \x00\x0c\x00$\x024\x00\x03\x00\x01\x04 \x00\x13\x00$\x02X\x00\x03\x00\x01\x04 \x00\xc8\x00\x16\x02|\x00\x03\x00\x01\x04 \x00\xc9\x000\x02\x92\x00\x03\x00\x01\x04 \xd9\x03\x00\x1a\x02\xc2www.glyphicons.com\x00C\x00o\x00p\x00y\x00r\x00i\x00g\x00h\x00t\x00 \x00\xa9\x00 \x002\x000\x001\x004\x00 \x00b\x00y\x00 \x00J\x00a\x00n\x00 \x00K\x00o\x00v\x00a\x00r\x00i\x00k\x00.\x00 \x00A\x00l\x00l\x00 \x00r\x00i\x00g\x00h\x00t\x00s\x00 \x00r\x00e\x00s\x00e\x00r\x00v\x00e\x00d\x00.\x00G\x00L\x00Y\x00P\x00H\x00I\x00C\x00O\x00N\x00S\x00 \x00H\x00a\x00l\x00f\x00l\x00i\x00n\x00g\x00s\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x001\x00.\x000\x000\x009\x00;\x00U\x00K\x00W\x00N\x00;\x00G\x00L\x00Y\x00P\x00H\x00I\x00C\x00O\x00N\x00S\x00H\x00a\x00l\x00f\x00l\x00i\x00n\x00g\x00s\x00-\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00G\x00L\x00Y\x00P\x00H\x00I\x00C\x00O\x00N\x00S\x00 \x00H\x00a\x00l\x00f\x00l\x00i\x00n\x00g\x00s\x00 \x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00V\x00e\x00r\x00s\x00i\x00o\x00n\x00 \x001\x00.\x000\x000\x009\x00;\x00P\x00S\x00 \x000\x000\x001\x00.\x000\x000\x009\x00;\x00h\x00o\x00t\x00c\x00o\x00n\x00v\x00 \x001\x00.\x000\x00.\x007\x000\x00;\x00m\x00a\x00k\x00e\x00o\x00t\x00f\x00.\x00l\x00i\x00b\x002\x00.\x005\x00.\x005\x008\x003\x002\x009\x00G\x00L\x00Y\x00P\x00H\x00I\x00C\x00O\x00N\x00S\x00H\x00a\x00l\x00f\x00l\x00i\x00n\x00g\x00s\x00-\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00J\x00a\x00n\x00 \x00K\x00o\x00v\x00a\x00r\x00i\x00k\x00J\x00a\x00n\x00 \x00K\x00o\x00v\x00a\x00r\x00i\x00k\x00w\x00w\x00w\x00.\x00g\x00l\x00y\x00p\x00h\x00i\x00c\x00o\x00n\x00s\x00.\x00c\x00o\x00m\x00w\x00w\x00w\x00.\x00g\x00l\x00y\x00p\x00h\x00i\x00c\x00o\x00n\x00s\x00.\x00c\x00o\x00m\x00w\x00w\x00w\x00.\x00g\x00l\x00y\x00p\x00h\x00i\x00c\x00o\x00n\x00s\x00.\x00c\x00o\x00m\x00W\x00e\x00b\x00f\x00o\x00n\x00t\x00 \x001\x00.\x000\x00W\x00e\x00d\x00 \x00O\x00c\x00t\x00 \x002\x009\x00 \x000\x006\x00:\x003\x006\x00:\x000\x007\x00 \x002\x000\x001\x004\x00F\x00o\x00n\x00t\x00 \x00S\x00q\x00u\x00i\x00r\x00r\x00e\x00l\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\xff\xb5\x002\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x17\x00\x00\x01\x02\x01\x03\x00\x03\x00\x0d\x00\x0e\x01\x04\x00\x96\x01\x05\x01\x06\x01\x07\x01\x08\x01 \x01\n\x01\x0b\x01\x0c\x01\x0d\x01\x0e\x01\x0f\x01\x10\x01\x11\x01\x12\x01\x13\x00\xef\x01\x14\x01\x15\x01\x16\x01\x17\x01\x18\x01\x19\x01\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e\x01\x1f\x01 \x01!\x01\"\x01#\x01$\x01%\x01&\x01'\x01(\x01)\x01*\x01+\x01,\x01-\x01.\x01/\x010\x011\x012\x013\x014\x015\x016\x017\x018\x019\x01:\x01;\x01<\x01=\x01>\x01?\x01@\x01A\x01B\x01C\x01D\x01E\x01F\x01G\x01H\x01I\x01J\x01K\x01L\x01M\x01N\x01O\x01P\x01Q\x01R\x01S\x01T\x01U\x01V\x01W\x01X\x01Y\x01Z\x01[\x01\\\x01]\x01^\x01_\x01`\x01a\x01b\x01c\x01d\x01e\x01f\x01g\x01h\x01i\x01j\x01k\x01l\x01m\x01n\x01o\x01p\x01q\x01r\x01s\x01t\x01u\x01v\x01w\x01x\x01y\x01z\x01{\x01|\x01}\x01~\x01\x7f\x01\x80\x01\x81\x01\x82\x01\x83\x01\x84\x01\x85\x01\x86\x01\x87\x01\x88\x01\x89\x01\x8a\x01\x8b\x01\x8c\x01\x8d\x01\x8e\x01\x8f\x01\x90\x01\x91\x01\x92\x01\x93\x01\x94\x01\x95\x01\x96\x01\x97\x01\x98\x01\x99\x01\x9a\x01\x9b\x01\x9c\x01\x9d\x01\x9e\x01\x9f\x01\xa0\x01\xa1\x01\xa2\x01\xa3\x01\xa4\x01\xa5\x01\xa6\x01\xa7\x01\xa8\x01\xa9\x01\xaa\x01\xab\x01\xac\x01\xad\x01\xae\x01\xaf\x01\xb0\x01\xb1\x01\xb2\x01\xb3\x01\xb4\x01\xb5\x01\xb6\x01\xb7\x01\xb8\x01\xb9\x01\xba\x01\xbb\x01\xbc\x01\xbd\x01\xbe\x01\xbf\x01\xc0\x01\xc1\x01\xc2\x01\xc3\x01\xc4\x01\xc5\x01\xc6\x01\xc7\x01\xc8\x01\xc9\x01\xca\x01\xcb\x01\xcc\x01\xcd\x01\xce\x01\xcf\x01\xd0\x01\xd1\x01\xd2\x01\xd3\x01\xd4\x01\xd5\x01\xd6\x01\xd7\x01\xd8\x01\xd9\x01\xda\x01\xdb\x01\xdc\x01\xdd\x01\xde\x01\xdf\x01\xe0\x01\xe1\x01\xe2\x01\xe3\x01\xe4\x01\xe5\x01\xe6\x01\xe7\x01\xe8\x01\xe9\x01\xea\x01\xeb\x01\xec\x01\xed\x01\xee\x01\xef\x01\xf0\x01\xf1\x01\xf2\x01\xf3\x01\xf4\x01\xf5\x01\xf6\x01\xf7\x01\xf8\x01\xf9\x01\xfa\x01\xfb\x01\xfc\x01\xfd\x01\xfe\x01\xff\x02\x00\x02\x01\x02\x02\x02\x03\x02\x04\x02\x05\x02\x06\x02\x07\x02\x08\x02 \x02\n\x02\x0b\x02\x0c\x02\x0d\x02\x0e\x02\x0f\x02\x10\x02\x11\x02\x12\x06glyph1\x06glyph2\x07uni00A0\x07uni2000\x07uni2001\x07uni2002\x07uni2003\x07uni2004\x07uni2005\x07uni2006\x07uni2007\x07uni2008\x07uni2009\x07uni200A\x07uni202F\x07uni205F\x04Euro\x07uni20BD\x07uni231B\x07uni25FC\x07uni2601\x07uni26FA\x07uni2709\x07uni270F\x07uniE001\x07uniE002\x07uniE003\x07uniE005\x07uniE006\x07uniE007\x07uniE008\x07uniE009\x07uniE010\x07uniE011\x07uniE012\x07uniE013\x07uniE014\x07uniE015\x07uniE016\x07uniE017\x07uniE018\x07uniE019\x07uniE020\x07uniE021\x07uniE022\x07uniE023\x07uniE024\x07uniE025\x07uniE026\x07uniE027\x07uniE028\x07uniE029\x07uniE030\x07uniE031\x07uniE032\x07uniE033\x07uniE034\x07uniE035\x07uniE036\x07uniE037\x07uniE038\x07uniE039\x07uniE040\x07uniE041\x07uniE042\x07uniE043\x07uniE044\x07uniE045\x07uniE046\x07uniE047\x07uniE048\x07uniE049\x07uniE050\x07uniE051\x07uniE052\x07uniE053\x07uniE054\x07uniE055\x07uniE056\x07uniE057\x07uniE058\x07uniE059\x07uniE060\x07uniE062\x07uniE063\x07uniE064\x07uniE065\x07uniE066\x07uniE067\x07uniE068\x07uniE069\x07uniE070\x07uniE071\x07uniE072\x07uniE073\x07uniE074\x07uniE075\x07uniE076\x07uniE077\x07uniE078\x07uniE079\x07uniE080\x07uniE081\x07uniE082\x07uniE083\x07uniE084\x07uniE085\x07uniE086\x07uniE087\x07uniE088\x07uniE089\x07uniE090\x07uniE091\x07uniE092\x07uniE093\x07uniE094\x07uniE095\x07uniE096\x07uniE097\x07uniE101\x07uniE102\x07uniE103\x07uniE104\x07uniE105\x07uniE106\x07uniE107\x07uniE108\x07uniE109\x07uniE110\x07uniE111\x07uniE112\x07uniE113\x07uniE114\x07uniE115\x07uniE116\x07uniE117\x07uniE118\x07uniE119\x07uniE120\x07uniE121\x07uniE122\x07uniE123\x07uniE124\x07uniE125\x07uniE126\x07uniE127\x07uniE128\x07uniE129\x07uniE130\x07uniE131\x07uniE132\x07uniE133\x07uniE134\x07uniE135\x07uniE136\x07uniE137\x07uniE138\x07uniE139\x07uniE140\x07uniE141\x07uniE142\x07uniE143\x07uniE144\x07uniE145\x07uniE146\x07uniE148\x07uniE149\x07uniE150\x07uniE151\x07uniE152\x07uniE153\x07uniE154\x07uniE155\x07uniE156\x07uniE157\x07uniE158\x07uniE159\x07uniE160\x07uniE161\x07uniE162\x07uniE163\x07uniE164\x07uniE165\x07uniE166\x07uniE167\x07uniE168\x07uniE169\x07uniE170\x07uniE171\x07uniE172\x07uniE173\x07uniE174\x07uniE175\x07uniE176\x07uniE177\x07uniE178\x07uniE179\x07uniE180\x07uniE181\x07uniE182\x07uniE183\x07uniE184\x07uniE185\x07uniE186\x07uniE187\x07uniE188\x07uniE189\x07uniE190\x07uniE191\x07uniE192\x07uniE193\x07uniE194\x07uniE195\x07uniE197\x07uniE198\x07uniE199\x07uniE200\x07uniE201\x07uniE202\x07uniE203\x07uniE204\x07uniE205\x07uniE206\x07uniE209\x07uniE210\x07uniE211\x07uniE212\x07uniE213\x07uniE214\x07uniE215\x07uniE216\x07uniE218\x07uniE219\x07uniE221\x07uniE223\x07uniE224\x07uniE225\x07uniE226\x07uniE227\x07uniE230\x07uniE231\x07uniE232\x07uniE233\x07uniE234\x07uniE235\x07uniE236\x07uniE237\x07uniE238\x07uniE239\x07uniE240\x07uniE241\x07uniE242\x07uniE243\x07uniE244\x07uniE245\x07uniE246\x07uniE247\x07uniE248\x07uniE249\x07uniE250\x07uniE251\x07uniE252\x07uniE253\x07uniE254\x07uniE255\x07uniE256\x07uniE257\x07uniE258\x07uniE259\x07uniE260\x07uniF8FF\x06u1F511\x06u1F6AA\x00\x00\x00\x00\x01TP\xc3\x17\x00\x00PK\x07\x08\x9a\x17<\x9c\\\xb1\x00\x00\\\xb1\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00fonts/glyphicons-halflings-regular.woffwOFF\x00\x01\x00\x00\x00\x00[\x80\x00\x0f\x00\x00\x00\x00\xb1\\\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00FFTM\x00\x00\x01X\x00\x00\x00\x1c\x00\x00\x00\x1cm*\x97\xdcGDEF\x00\x00\x01t\x00\x00\x00\x1f\x00\x00\x00 \x01D\x00\x04OS/2\x00\x00\x01\x94\x00\x00\x00E\x00\x00\x00`g\xb9k\x89cmap\x00\x00\x01\xdc\x00\x00\x02\xc0\x00\x00\x06r\xda\xad\xe3\x81cvt \x00\x00\x04\x9c\x00\x00\x00\x04\x00\x00\x00\x04\x00(\x02\xf8gasp\x00\x00\x04\xa0\x00\x00\x00\x08\x00\x00\x00\x08\xff\xff\x00\x03glyf\x00\x00\x04\xa8\x00\x00M\x17\x00\x00\x94\xa4}]\xc2ohead\x00\x00Q\xc0\x00\x00\x004\x00\x00\x006\x05M/\xd8hhea\x00\x00Q\xf4\x00\x00\x00\x1c\x00\x00\x00$\nD\x04\x11hmtx\x00\x00R\x10\x00\x00\x01O\x00\x00\x03t\xd2\xc7 `loca\x00\x00S`\x00\x00\x02'\x00\x00\x020o\xfb\x95\xcemaxp\x00\x00U\x88\x00\x00\x00 \x00\x00\x00 \x01j\x00\xd8name\x00\x00U\xa8\x00\x00\x01\x9e\x00\x00\x03\xa2\xb3,\xa0\x9bpost\x00\x00WH\x00\x00\x04-\x00\x00\n\xd1\xba\xa3\xe55webf\x00\x00[x\x00\x00\x00\x06\x00\x00\x00\x06\xc3\x18TP\x00\x00\x00\x01\x00\x00\x00\x00\xcc=\xa2\xcf\x00\x00\x00\x00\xd0v\x81u\x00\x00\x00\x00\xd0vs\x97x\xdac`d``\xe0\x03b \x06\x10`b`d`d\x14\x03\x92,`\x1e\x03\x00\x05H\x00J\x00x\xdac`f\xe9f\x9c\xc0\xc0\xca\xc0\xc2\xcc\xc3t\x81\x81\x81!\nB3.a0b\xda\x01\xe4\x03\xa5\x10\x80 \x89\x1d\xea\x1d\xee\xc7\xe0\xc0\xa0\xf0\xff?\xf3\x81\xff\x02@u\"\x0c\xd5@aF$%\n\x0c\x8c\x001\x96\x0b\x0c\x00\x00\x00x\xda\xed\x94?hSA\x1c\xc7\x7f\x97\xa4iS\xc4\xc6\xfe\x89\x8dm\xdf\xbd44\xb1\xad\xd0,\x0eq\xcaPK\x83 q\xd2\x0c\xd2XE\x1a]\xb2(\x04\x142 \x01\x87.\xa5\xd4\xa9\x83]\xb4\x82 \"\x0eE\x1c\x9cD\xb7\n\xad\xa5\xb9\xdfi]D\xd4\xa1ZJ\xf5\xf9\xbd\\\x06\x11\xb5\xba8\xf9\xe0\x93\xcf\xef\xbdw\xef\xee\x9bw\xbf\x84\x88\x9a\x88\xc8\x0f\x0e\x81V\"\xb1F\x02\x15\x05\xa6pU\xd4\xaf\xfb\x1b\xd7\x03\xe2.\xce\xa7(\x83g\x0e\x92K\xc34O\x0bn\xab;\xe2N\xb8\x8b\xeeR\x7f{\xbcg`'!\x12\xdb\xc9P\xb2M\xf9UHE\xd5\xa0J\xab\xac\xca\xab\x82*\xaa\xb2\xaa\xaaY\x0eq\x94\x079\xcdc\x9c\xe5<\x17\xb9\xccU\x9e\xe19\x1d\xd4!\x1d\xd1Q\x1d\xd3I\x9d\xd6Y\x9d\xd7\x85-\xcf\xf3\xb0\xa2KC\xf5\x95\xe8\x17+ \xd5\xa4\xc2\xcaU)\x95Q9\xac4\xa9J\xaa\xa2\xa6Yp\x98]Nq\x86\xc79\xc7\x05.q\x85\xa7yV\x13V\n\xebn\xac\x14\xd7)\x9d\xd19\xbb\x92\xf7\xca[\xf5\xce{\x93\xaa\xa5\xf6\xbav\xbfV\xac\xe5\xd7\x9b\xd6\xbe\xac\xf6\xadFWb+\x1d+{\xdd>\xb7\xd7\x8d\xb8a|\xe3\x80\xfc*\xb7\xe4g\xf9Q\xbe\x95\x1b\xf2\x8a\xbc,K\xf2\x82<'\xcf\xca\xd3\xf2\xa4\x03W@\x15\xf5Ex\x1a\xcc\xa2\xbeD\xc4\xc8\xc3&\xc3U\x18\x19\xd8d\xb8\x06#\x03\x9b\x0c\x18\xcb\xc8\xc0&\xc3\x0d\x18\x19x\x0c\xf5Mx\x1c\x98<\xb7a\xe4a\x93\xe7\x0e\x8c,l2<\x80\x91\x81M\x86\xc702\xb0\xc9\xf0\x146\xf3\xce\xa0^\x86\x91\x85\xe7P\xbf$\xd2\x906{\xb8\x0e\x87,\xb4\x01#\x9b\xc6\x9e\xd0\x1b\x18{\xa0M\xcewp\xccB\xef\xe18H\xa2\xfe\x00#\xb36\x997ad\xd6&'~\x89\x1a95r\n3w\xc1\"\xd0\x0f[\x9eEt\x92\xd8\xdcW\x87\x04:\xfd\xd3\xad:$\"\x14\xf4\x99>2\xcd\xffc\xff\x0b\xf25*\xdf.\xfdl\x9f\xf4\xff\xe4N\xa0\xfe/\xf6\xff\xf8\xfeh\xfe\x8b\xb1\xc1]Gt\xfd\xe9T\xe8\x81\xdf\x1e\xdf\x00\x8f\xd1\x0f\x18\x00(\x02\xf8\x00\x00\x00\x01\xff\xff\x00\x02x\xda\xc5\xbd |\x1b\xd5\xb50>w\x16\x8d\xd6\x19m#Y\xb6e[\x92%Y\xde-YR\x1c'r\xf6\x84\xc4Y\xc8j\xb6\xb0D%\x10 \x81,@\xd8B\xd8K\x1bZjH\xd9\xda\xa4@\x1a\x12b\x02\xa5\xa5\xa4-\x85R\xf4\xca\xeb+\xa5n\xfbhK\x9b~\xaf\xe5\xcb\xeb\xa3\xbc\x96\xa6\xa5$\xd6\xe4;\xe7\xceh\xb5\x13\xe8\xeb\xff\xfd\xfe^f\xee\xdc\xb9s\xef\xb9\xe7n\xe7\x9c{\xce\xb9\x0c\xcb\xb40\x0c\xb9\x8ckb8Fd:\x9f%L\xd7\x94\xc3\"\xcf\xfc1\xfe\xacA\xf8\xd5\x94\xc3\x1c\x0bA\xe6Y\x0e\xa3\x05\x8c>,\x1a\xc8\xd8\x94\xc3\x04\xe3\x13\x8e\x80#\x9cp\x84Z\xc84\xf5\xd8\x9f\xfe\xc45\x8d\x1dma\xdfd\x08\x93e\xb2\xfc ?\xc8\x9c\x07y\xc7=\x8d\xa4\x81\xf8I:C\x1a\x89\xc7 \x93D\xdc\xe3\xf5(n\x08I\xa4\x8dx\x1b\x88L\x0c\x91.\x021\xa2!\x14\x84P'\x99JD\x89t\x91Hj\x80@L4\x92\xec\x85P\x86\xf4\x93h'\x19 )\xc8\x11b\xd2)vH\x8eX,f\xf91\xd1c\\'\xb2\xe2cG\xcd\x0e\xd6\xc0\xb1\x84u\x98\x8f>\x06\x11\xeb\x8c\x1e\xf11\xd9\x1c\x0b~\xc2t\xfc\xe0?\xf1\xf1\x84\xe9\x18\xf8!x\xa1\xf8\x08\xc1\x03T_q\x04\xe2\x1e?q\x1bB\x01\x87\xdb\xd0F\x82\x91\xa4#\x10\x8cL%\xbd\xa9D\xc0\xd1\x9b\"\xaf\xe4\x14?Y\xad\xf8\xfd\x8a\xba\xc7\xaf\xc0\x83\xba\x07\x1f\xc8j??8>N\xd1Skem\x84\xb2\xa6AY\xb3\xb5\xb2Db\x10\xa14\x0d\xd9J)\xa4\x95;\x95@\xb9\x1aj\x93\xc5P$\n\x98\xef'qh\xae8`\x9b\xeb;a\x16\x8c\xea\x03\x06\x81X\xcd\x06\xc36C\x8d\xf9F\xe2*\x84d\xcb\x03\x16Y\xfdc\xe1\xb1\x18\xda\"\x18\xd4\x07\x8c\x82\xf9\x84\xcf\xf9\x15\xa3\xdb\xf8\x15'?h\xc6L\xacV\xe3\x97\x8c\xd6,\xbd>c\x91e\xcb3e\x11V\x03\xb9\xd2h\x86\x0f =C\xfb\x91\xc0\x7f\x9a\x7f\x86\xe9\xc7~\xe4\xf5xC\xbd\x9d\\((qb@\x0c\x18\x14\xb84\xf0\x89x\x86K&h\xd7\x81\xce\x11\x0d\xa5\x13\xa94\\2\x04\xba\xc7\xb1\x0f6N1|-\xd4;\xad\xcf\xebj\x9b\x14\xef\x96\xc9\x0dYu\xd4@\x86\xe1j\xea\xee\x9b\xd1\xabx\xfa\xa6\xf5\x86\x9ei\xb8\xe4\x8a\xa7\xfemK\xf3\x0c\xeb\xdb\xd9\x8dD\xf8E\xf6\x0ew\xa6q3\xff\xcc\xb7.\xbb\xbccAw@\xb64t.\x8eg\xe3\xf1\xec\xfckg\xb4\xc9r\xb0{~\xdb\xd3Wl~\xac{\xff\xd6lW2\xbb\xea\xf6\xf0}\x0c\xc327\xd06\x1ea2\xcc\\\x806\x10o\x10\x94z@\xb3$\xb4\x11\xf1\x13\xa1\x1d\x1a\xde\xebH\xc4S\xc9\xdeH\x88\x1c \xabg\xae\x9b\xd1\xed\xb1\x12b\xf5t\xcfX7\xf30K\x9at\xd4\xdec1\x7f\xc1,\xab\x7f\xd5\x1f7\x97B\xf2\x0boL\xeb\xe8\x98\xc6\x8f\xd46\x0f\xc4\x17\xb76[,\x96\xe6\xd6%\xf1i\xe1Z\x0d\xbf\x87,\x92l>T\x86p\xf2K\xb3\x9cSGg\xac\\>\x0d\xf1\x9d#\xbb\xf8A\xf6\x08#3\x8c\xab\xd8E\xb5\x8ey\x82k\xc2\xee6v\x14\xae\xec\x11\xda\xe7\xe8\x85\xc1\xba\xe7\x18\x86;\x06u\x0f3\xd3!\x1bZI\x1c\xce8\xec\x13\x98M\x00\x86k?\x1d\xb38\xb6C\x98\xa3Wq{`\xecC*\x89\xd0\x04\x11h>H\x90\x81\x04\xdc1\xbf\x12_s\xf6\xd9k\xe2\x8a\x7f\xech)\x9c\x9b\x9e\xaeoj\xaaOO'\xbb\n!~dX\xf1g\xcf\xfbB(\xf4\x85\xf3\x86\xfd\xca0<\x0dkOYx\xcae\xa7\xac\xa9\xb1\xc6\xa7\xc4\xad5k\xa6\x0c\x0f\x97=d\x0b\xe3\xb2\xf0\xd3\x03\xcf\xa7> \xed\xfc+\xfct\xc6C\xe7-o\n\xc7\xaa\x86\x02\x84\x1d/\xe4\xc3\xf5_ko\xef\xdc\xb6\x7f\xff\xb6\xbcs\xf1\xd5+f\xb0\xff\xceO\xdfz\xb1tp\xdbu\x077-\x99}\x85d\xf5\xed\xfe9\xc5 \x03s\xe0\x08\x7f\x88\xa9e\x1a \x8c\xb3\\9.H4\x92!0\x8f\xa5S\\ \xca\xb1\x7fk2\x99\xef\"?ip7\x9c\\\x02\x172z\xa7\xd9\xd4\xd4l\xde\xb0\xd1t=\xb9\xee\x85W\xf9\xe7\\!\xfbKyOXimU\xc2\xec\x1f\xbenov\x9b\xec\x0f\x0c\xdb\xc7\x1a6\xb2\x1e:\xbd\xe8\xe5\x0d2\x16\xc6\x0b\xf3LZkA\x18\xfdA\x1c\xcd^\xe2qC\x18\xe6\x99\xde\x94 &P\x05\xe6\x1d\x88\xef\x15aF\xc6\xea\xa5I\xaa0\xdc\xe3>\xfe&\x18\xef\xf9\x7f\x85Q\x0b\x17\x81#F\xa3Q\xfd\xbb\xd1l\xe6>\x0dA\xb3\x19\x1f\xce\x87q*\x98O\xee\x80\x84\x10\x82\xe1\xad\xfd\xe3\x18\xcf\xff\x8b\xd1\xc8\xa6\x8d\xe6_@27\xa6\x15\xccl\xc4,\xa8\x7f\x82\x8f\x05s\xfe\x17\xf8\x89\xd1\xe8\xbe\x05f\x07\xc8\x0b\xbe6\xe2p7\x02\xfc\xdc\xa9?\x9d\xfa\x13\xffM\xfe\x9b\x8c\x89\xb11v\x88A\x98\xdc2\x89\xa6]$j\"\x82\x8b;\x1a\x91v\xdblk~va0\xbf\xfbg\xec\xa5j\xa3\xfa\xdcz\xfe\x9b\xb6\xddRD:\xffg\x17\xa9\xd7\xe6\xbf\x08\xb1c\xeb6\x92\xc5\xc5yw\x04\xfa%\xf4g\xe2(\xc3\xbe\x83\x04\xd8#'\xb4\xceuB\xb5\xf2#\xec=\xf9_@?\x83>\xc6F\xd8\x08\xfdVb\x8c0\x9e\x1fa\x1a\xe1!\xacaL4t\x12Xv\xbc\x0e\xa1\xfc\x01:\xc5F\xf6\xf6h\xf7\xb29\x8b\xefj^\xb5x\xde\x8c\xfc\xbe\xa1\xe9z\xd0\xcf}\xb4Wn\x08\x8e}7}\xb6\xd7\x17\xbbj\x93\xaf\xc6\xce\x9a\x1e\xce\xefi\xbdH\xa9\x8d\xad\xbf\xba\xb6\xc6\xc1\xde\x1ci\xa5\xfd\xc5t\xea\xef\xfcK\xfcS\x8c\x9f\x89a\xcd\x1bXE\xf4\xbaE\xbabb\x1b\x1aBQ1\xd8\xc9\xf6f\x08\x1f\x94\x08t\x91x\x86\xf4F\xc8\xae\xdc\x0b\xb7-\"d\x11qA\x13\xf7\xd7\xc6\\\xea\x1f\xb7~F`\xb3\x10\xbb\xe86\xb2i\xe4\x81\x95+\x1f\xc0\x0b\xff\xd4\xa2\xdb^\xc8\xb2\xc2}\xd7\xa9\xef\xd7\x86k&\xbb\xdd\xc4\xb9\x10\xbe\xbb\xed\x05\xc8\xe0<-\x0d\\\xe8\x9c;\xc4\x1f\xe2g1>\xa8w\x86\x050\xdc0\xdfv\xf2\xc9^x \xec\xdd\xdd7l\xdb<\x94\x9ay\xdd\xce}\x99\xccS\xb7o\x9b9\xe9\xdc-\xdb\xae\xe3\xbe6k\x9e\xd0\xb1l\xcb\xb4\xbe\xebn\xb9\xf9\xf0\x8a\x15\x87o\xbe\xe5\xba\xbei[\x96u\x08\xf3\x10\x97\xa7~\xc2\xac\xe6o\xe0\x1f`j\xe0\xc1\x95\x8a{i\xd7\x14\\\x1eC4,\x18\"iW8\x92J\x90\x07o\x13\x15\xf1V\xf2\x84bp\xa8\xfbw\x88\xb2C\xfd\xaa\xba\xdf!\x8b;\xd4'\x1c\x067\xd7D.v\xb9\xd4\xc7\x1d\xd6\x8f\xd4\x0dn\x8b\xf5o\x1fZ-n\xb2\xeb\xa4\xd5\xc1\xb0e\xf9\x07\xcfP\x82\x10\xf2\x8aio4\x1d\x8a~LY\xe4/\x7fzm\xfew_\x9d\xff\xf2\x1f\x16\x9d\xbe\xd8\xecg\xfe\xcf\xbd\x9f\xfe\xfd\xa7\x7fR\xde\xcf\"t\xde\xa0\xd3&No\x02N\x80\xa5)4\x1d\xc6\xc9M\x0b\xb3C\xdbG2\x11\xab\x89\\j\xb2\xca8\x90d-\x1c\xc9@>#\xdbOt^\xb6\xc0\xec5\xbc+x\xcd\x17\x98e\x19.^\xe1]\x83\xd7\xbc\xe0\xb2\xce\x13\xdbG\xa08\x9b^\xe6 \xf4m\x17\x8c\xf7(\xd3\xc6t1 \x18\xf7s\x99\x05\xccbf\x19\xb3J\x9b\x01\xb0\xdf\xd2 \x0c\x97\x17%\x91\x8c\x91\xa0\x01\xe2<\x89\x00\xac4\x8e\xdeH\x02\xe2\x04\xf8\x0f\x94\xdd\xc5@e\x9a\xea\xf78C\xc8\x1a\xd4\xf2\x8a,\xbb\x17\x065<\xc2(\x97\xe5k\xb2c5Y\xaeI\xbf\xfe\xb6\xec\xcd\xd8\x7f\x97\xe2\xf9A\xf8\xfa]|\xc5\xd7\x9a\xe5l6+\x9b\xd5=\xf8HV\xe3c\x0eb\xb4K\xd5\x8bB\xb46\xdfi4\x95\x0c#\xb4\x8b\x19\x18_\xdb\x18\xa9|&\x1f\xf3>NvQ\x8ak#\xaepW\x95=\xe4\xbfu\xba7\x94\x1a\xdbH\xc9\xb0R$\x0d\xe7\xf7\x9d\xee\x0d\x03\xb3[5\xec\x8b\x99\x0b\x99\x0d\xcc\xcd\xccg\xa1\x16 \xad\x03\xb5\xe9\x1d%\xf01\xcf\xe4\x7f9}\xbc\xb0\xd0\xfb\xc9\x13\x13\x05\xc7\xfe\xfa\xcf&@$\x16\x1f&\xb8\xa8\x1b\xff\xb9\xf7\x8c\xa1l\xac\x94\xf0=\x0e\xd31RI\xf1\x90\x7f\xf2}9\xe6\xd8#\x18\xce\xcf\x82\xabz\xfb?\x16?1z&\xae\xf4\xc4\xb1\x1a_\x10a\xda\xf9c|\x13P\x07\x8cI[\xed\xdd:u\xd0;\xa0\xaf\xfe\xe4\xc7l\xbf\xd1->k4\x8e\xfd\x19\xe6G\xf5\x16\xa3\xf1Y\xd1m|Z\xf4\x90w\xe0\x0d}\x18\xfb\x93\xd1Hn\xd1R=-B\xbe\xeb\x99\xf5\xfc\x0c~\x06\xe5m\xbc\x90\xa7\x89.\xd9\x90\xb1 .\xc0\xc3\xf5\xa6Mz\x11^,\x97\xbb\xeb0\x90\x13\x7f%\x16\xa3\xf1\xb0\x11\xca8\xae\x1e\x17\x15\x08\x1a\x89E\xfd\xab\x16G\xac\xc4**|\xffsg|o\xd4\xf2\xb1\x8a\xc0\xb9zO\xfd\x17\xff\x1a\xbf\x1b\xd6\xac0s\x96\xbez\xe2\xda\xe9.\xac\x9d\xe3WN\x81\xb6^\xb1 \x8b\x84yHk<\x8d\x02v3t\x01{\x058-\xd9|\x02\xc3'\n\xf8\xabe\xea\xf8a~\x18\xd6\xec\xc5H94\xb2\xc8\x11x\xbc\xa2\xd7\x03A\xc5-\xb3@\xfcy\x0dbT4@0\x14\xecb#]D\x8cD\xd3\xd1\x08\x04\x93\xbd\x03lj\x80DSio:\x05Ag\xd0\xe0\xf6\xc4S\xbd\xecP \x16\x11z:\x84;\xa6\xb6-\xe1|\x12yH\x10\x1e\"r\x0d\xb7\xa4{\xd2\x1dB{\\\x88\xb45\x16RLi\x87\x146\xf6A\x83\xe1A\xd6\xe6\xe3\x96tM\xbe]\xe8\xe8\x81\x14\xdb\x0e\xdft\xd3\xe1\x9b\xf8a\xf8R\xf2\xb1K\xba\xfb\xe0\xcb\x1eC\xa4\xad!\xd8\x121\xf4\xb4C\xde\xedgC\xde\xec\x83\x82\xf0 +\xf9\xb8\xb31EG\xb7!\xd2\xda\x14\x80\x14\xddXz\xfb\x12\x96\x96\xae\xee\xbe\xe9\xd9\x9bnz\x96\x11\xb5v\x12\xdc@\xb1x\x99\x00\xf4\xed\x18\xf4\x9b\x1e\xca-#i^\xa0\xcf\x13x\xf1*\x81$)\xae\xce\xc0\x18W\xfc\x92\xe3\xa4=\xd6O\\f\xf9\xe4\xf3\x80[W\x7f\x8c\xb4\x93\xf6\xfeX~V\xac?\xab\xff\x08\xee\xfe\x18\xd0\x0f\x0b`Lei\xac::v4\xd6\xdf\x1f\x03\x02$?\x8b=R\xfe\x0f\xf3\x98\x95a\x04#\xffc\xa4\xf7]8Y\x01\xe5\xddFJ\xe2\x99b\x08&\x08'{%LC\xecE\xc0\xcf\x1c\xa2\xad\x89\xcd\x0c\xb7Cf\x81]\xc7^$\x8a\xf9/\x19\xcd\xf9\xef\xd2f\xdf\xaa\xdeM;\xc3\x80\x19\xda;\xab\xf3\xc9\x0e\x9c\x85 \xa5\xb0\xca\x08\x90\x846\xf9\xb0CX\x1b\x9d\xd5V\xb8\xa5\xc0\xa7\xf0#\xea\xc6X\x7f~\x0bF\xf0\x83\xda<\x7f\x02\xe7 :\xfevC\xbf\xafc\xba\xb5yB\x1bp\x13Lv\x8a\xa3\xac\x8f\xd31\xf0\x1f\x7f\xd0F\x94v#\xdf9\x86\x03\n/\xea\xf68VF\xeb\xa901\x14\xd3\xe0\xad_K\x03\x17\x1b\xf4\xed?\xca\xe6x\x81>\xa3}\xfa\xd4#\x80G7\xd4\xd1\x82\\W\x8cp!.@\x12\x1c\xfc\x12\xb8\x08\xee\xfc\xbb\xb1\x0fb\xf9w\xc9\xa1\x1f+{\xdco\xaa\x8f\xd5\x1d\xad#\xbb\xd4\x8dP\xc3Q\xd2\xaen\xc4\xab66\ncZ\x81\x11\xad\x8f\xe7D\x89\xa1\xa5\xe2\x92\xc2(. \xb0\x9f\x14\xba\x10\x1b\x81u\xef;n\x8bM}\xd1\x16\xc1\x8b\xc5\xfd\x1d?\xbb\x9c\x82\xaa\x11\x9e\x10\xe4v\xcat\x9e\xc9x\xed\xeaF\xbb\x9d\xec\xb2{\xc9+\xc8\x14\x96\x13\x9d\xb2\xf9\x10`\xa2\n\xd7=\x9f\x04\xd7\"\x07\xa0r\x05P\xcf\x80l\x98D\xeeV\xcc\xb6\xdf\x00\xa4\xbf\xb1\x99\x95\xbb?\x06\xe3\x00\xed\x1f\x01Z\x17@\xeb\xa2H\xff\xe4\xb0\x85]\x15\x9d\x1a\xba[\x1a\x98\xa53\xc0\xf6\x7f5\x80\xcc%\x10O\x0b\x1b\x01\xa8\xbc\xea\x1f)\xde\\^\x84\x8f\xd1\xe5 Z;\xfa\x98>\x8dF\xf7\xbatf\x1a\x9b-\x1aI\xbaz\xd3\xae\x0c\x11\x80\xe7\x00\x8cy\xfau\x811\xdcu\x99o<\x15\xe5:\xc9oa:uq\xdf\x14\x8d\x82\xd5w\xf2yk\x03k \xe2\x8b\x9c\x8b}0?jv\xb2\xabX+\xc0\xe8\x02\xe6\xdd\x05}V\xbb\x0f\x9b\xad\x10\xef\xe4G$s\xfe\xda\x1a\x9f\xba\n?2\xf26\x1f\xf9\xaa\xaf\x86\xfd\xb4Y\xcaI\x165c\x91$\xf3Cf\xfdb!\xafX\xa4*|F\xcf\xd4\xd6^\xba$\x7f\xdcp\xba7\xefp\xe4\xed55\xa7\xc5\xdd\x05\xdf\xb66[\xbfm\xb5\xe0jg\x81\xb9\xa8\xb0\xae\xa2l>\x9d*\xf6\xf1\x01\x12 \x15KO&\n \xb1\x898\xf7\xdc\x9d\xa2\x05:\xc7\xb0\x85\x17o\xbf\xea\xd6k\xf5\xa2\x87K\xe5m~\x99o\xbeS\xe4-*4\xa5E\xbc}P/\xfb\xda\xcd%\xa0\x0bk:\xa1e\xd7\"\xe51A\xe9J\x88\x96\xe8\xc2\xe2CAX\x9a\xb4\xb9\x8b\x8a8= \x00L\x83\xc5\xa2>\x08\xb0\xdc\xb1\x1ea\x19\xa6\xe5\xff\x97v{\xe4\x0e|K.3\x0b\xc6\xdb\xd7\xef\x80\xb7:\\\x0fB\xacx\xc7\x02\x1d\xa4\xfcw\xf0\xba\xe5\x0e\x98b\xc9e\x16\x1db\x80\xcf>\xd61\xdb\xbfv\x89H\xc5\x16?\xe4\x13f\xb9\x9b58\xd4\xf3\x0c\x86\xfe%\xcd6\x9b$\xc9\xb2\xdc'p\xa2L^H\xaf\xe2X\xcebp\x13I\x92V\x19qn\xd6\xe6\xbf\x07\x81\xde\xe9A\xe98\xa5\xe5K\x94g'i\x82!Uz\x86\xe1SE\x9a\x06\xaaI\xd7\xdf\x1d\xfb\xf5\xde5\x14\xd9\xf7\xfdN=\xf1\xbb\xfbhp\xcd\xdeV\xdc?\xa1\x9b(\xecE\xc5 \xff\xe0\x9a\xbd\xbf\xbeV\x1d\xa5\xb3r\xfb\xcd?\xde\xb4\xe9\xc77\x17\x9e\xae\xfd\xf5\xde\xfc\xcbV\xa3\xda\x8b\x89\xc9\xbf\xe2\xb5\x14.\xb4\xe3O\xf8\xb9\xdc;\xb0\x06\xf7\x95\xa4\xa0\xd1p\xa4\x00\x0b4\x9e\x90N\xe9RZm.\x04\x96O\xd4\xf8> Mu\xbe\x8fL'\xac\xc9j5\xa9\xaa\xe2\xd3\x08`\x1f;\xb4Mt\x8bAQ\xdc\xb6M\x84\x9b\x1b\xef\xf4y\xebV\xed\x99\xeb<`\x10\x91\x92\x16\x0d\x07$m)\xdey\x9a\xa4\xda\xb3\xd1X\x84\x99\xdbDa\xee:\x1d\xcc\xe1\x04\xdd\x81\x04\xaa\x9a\x04q\xbb1\x9dJ\xf6Fq\xb315\x01\xa4\xe4-\xdel\xb8\xe8\\\x83\x853\x89~X\xa1\xe6-2pF\xffD\xf0e\x89\xe9\xd6/\x7f\xf1f\x13!\x06\xaf\xe82\xae\xbdi\xe7:\xe0\x93=\x02\xc3h\xfd\xe0{\xfc%\xdc{t\x85^\x80\x14\x8d\xb6\x0b*\x1a\xc4P\x11\x88\x88\x06\x85\xf0\x0fB\xcd\xbd\x0e]\xee\xceY\xd3D3\xc0\xd8jd\x0d\x1b\xfa\xd3\x06\xd6\xd4*\xe6w|\xe2\xea\xbcGL\xcf\xbd}\xf9\x1b\xcb\x91k7\xb8\x8d\xc3\x87\xcf=0\xd7\xe46\x04\x84o\x7f\xa2z*\x06\xad\x9e\xb6\xe2zo\x82\x16\xf01~J\xe7w0\xfd0S\xcf\xd4e\x93Pw%\xa4\x04\x94\x90#@BJB \xc0\xa0\x0d%\x03\x02\x10\xd9\xf8+\x84\x92 \xfc'\xb8\xbd\x9c\xc0;\xa4\x0e%!&\xa9\xa7\x12\x0b)\xf0\x1eH\x06\xc8q \xee7f\xc9q\xf6H.\xa7\x8e\xe6\xb2\xec\xd0\xc9\xe7\x81!\xd8E\xda\xc7\x8ef\xb3\xec\x91,\x10\xfc9\xd5\x9a\x83$9\x94 \xe6H{~\x16i\x07\x9e\x80\xdb \x9fZ\xb3\xf0\x02)O|\x82\x8f!\"\x87\xfcD.K\x89\xd2Q\x0ca2\xd5\n%\xa9\xa3\x9a\x182W\x8c\x1f\xa5\x12\xc9\x82\\\x0f\xeb\x8e{\xe9\x16*\x99\xf5B{7\xe2,\x98\x0e9\x12.\xf8'ew U\x03^\xa8\x83W\xaf\x8f&\xde$\xbbr9\xbc\xb5\xe7rcG\xf5B\xf4\xe7\x1cwl\xac\xa6\xf2\xff\xe4\x92l\xf6<\xfc\xd1\xfa\xbe\x99\x7f\x12\xca\xb7\x01\xee\x19SQ\xc2\xe3\x82\x85\x88\x8fh\xec! i\xbf\xd1\xa8v\xe3\xee\xceJ\x02\x0d:\xb3\x7fY?\xfc\xf1#\xf9\x95\xb8_\xd3m4\xb2\xfbq[\xf0\x87\xfd\xfd\xcb\xfb\xfb\x0b}\xd7,\xbcE\xf3\xf5A{V\xe5\x1c\xd0\x9f\xba\x88\x89\x9c\xae\x14\xceP|\x9eD\xf6\xe5g\xa9?9M\xa9\xc5\xc7Id?{\xa4\x04\x03)\xae\xfb\x11\xca/\xc2\xf0\xd0 /\\[ \x88\xabJ\xf9\xd2\x8f\x83\xb9\x9d\xeb[\xe0\x9cf4\x03G>\xcb\x07\x01\xc1\xcc\x1e\xc1Q\x80K\xa0\xf3^\xa0\x0c\x17\x8cm\xd7\xe2\xb9\x17 \x86\xa6\x1c\x9bO\x97\xc7\x1f\xf9 \x01-7w\xea\x14]\xcb\xcc\x05\xea\xc2\x84\xf4<\xdd\x0eU3j\xc6\x8f,\xc4\xc9\x1d\xe4\x88:\x93\xbfY\x93\xb5q\xc5~\xa00\xb3\x99\x15\x08/\xa5m\x91\xac\xc5\xb5\x0f@C\x8a\x16\x97C\xdc\x15F\x80q<\xb7\xe9\x92y\xa4x\xcbh\x07\xfa\x8c\xf5\xc4\\\xf4\x8a\xa60=\x97RgY\xecd\x91(\xf5\x19\xbc(_\xf0\x1a2\x92\xb8\x8c\xd8\xc9\xcaa\xb3\x87_\xc4{p\xb7M\x0b\x14\x85\x15T*\xa1\x8b0\x9eU\xad\x94T\xb6\x98\xd9!\xb3\x05if$\x16\xd4\x9f\xd4(W\xe2\xa4q\xa5RC:P\xa0a3=b\xb2\xd1\x0b rK1'-\xbb{\xa0\xcd\xf6\x95H\xe8\xca\xbdH\x1c\xfd1\xca\xe1'`\xd9k\x1c\xcf\xafex\xa2$\x92\xbc.\xb9h\x8e{\xdc\x86`\xa4\x17F\xe9\xa4\x0bz\x9bE\xc30\xae\xf8c5x\x1dfM\xd1\xc4\x05\x04\x86\xe4\x8f\xbe}\xe7\x9d\xdf\xbeS\xfd\xef\x95S\xa6\xac\x9c\xc2\x0f\xc2K\xc5]N\x1d\x18\xebf'\xdbpP\xce\xb9\x13S\x1a\xa7`BmmH\xd2v9\xc44\xe1\x88\x84^\xecm \x8dD $\x11\xa1\x01\x98\x8a\x81,\x80'\xdc\x84\x1e \x84\x0bp\xecW\xc9\xad\xee\x16g\xd8dV/L\xb6;\x96\xaa\xd7M\x0eZL\xad\xf1\x06\xf5\xf3\x93\xea\xad\xb5\xa2H>{\x80,\xdf\xc3\x1f\x1a\xab\x8d\xb7\xba\x14\xc2\xce\x98\xb1\xaa\xe3\xd7\xf7\x9f\x13\xec\xac\xb7\xce\x98QSo\x0d\xdbl\xdc\xfb\xf9s\xc9\xbfh\xfd\x02\xf9\xff?A\xbf\x882q\xaa\xd3\xd0`\xc0\xdd5\xa0\x83\x80\x9c\x07Z\x80\x8f&\x05*\xea\x93X1L5\x01:\xd96\xa2\xeb\x04\xb4\x11\xf6\xcf\x82+\xd9\xdd\xdf\xeaO\x0f]ue\xb7j\x8d\xf5\x13\x83\xc5\x1b\xa8%?\xef\xdb\xbc&\xd3\xd8\xd1aW?{\xef\xa2\xcb\x1d\xad\xcb2[\xfe}\xc9\xd2\x1bW?\xce\xdeJ\xc4\x1a\x7fb\xf2\xd2\xce\x99\x9b\x17\xa5k\xcf\x11\x13-\\\x7f\x8d\xbb\xdeb7\x89sI\xec\xackf&\xce\x9b\xdcf\xea\xb9x~\xac\xbf\xb7n\xec\x99O-9\xf7V\xda\xe7\x01\xce\x0d\x94~c\x88W\"\xc8\x97y)b\\)\x842\x12MrW\xb1\xcbf\x88;M\xed\xf3U\xeb7\xa5\x83\x1c'[\x1b\x15\xaf\xcd\xc0\x8f\xf4\xb9\x92-c/\xf6\xb4\x18.\xbe\xd8\xbe\x94\x9b\xe6\xa8u\xd9M\x16\xe8\xfel\x9f&\x1f\xf8\x9a.\x1f\x08\xd3\xf59\xd4\xdb) G\xea\xd1\xda!\xc3!W* \xb86\x080C\x8a\xd1\x84#\x94\x16\xdcq\xa3\xc5\xe7\x8a\xd4\xf8rq\x9fO\xdd\xc8K\xc1ZO\xceW\x13q\xf9,\xc68\xcc\x81\x0f/Xp\xe3\x8d\xf0\xcf\xedT\x9a\x14\xc9\xc8\x91\xb1g<>\xc2\xc2\xa4)\x98\x14\x89[J8\xa3\x04o`\n\x1d;\xfa\xd4S\\\xd3S\xd0\x17\x02\xa7\xbe\xc6\x7f\xf6\x93\xc0\xe1\x12\x93\x01%\x9a\x86h~\xf0\xccp\xcc|J\xcb\xbe\x08F~K\x19\x18\xec=E0N\xee\xb8Q\x83X\xdf\xc7\x1a\xa9\xde\xc7*\xe7\x19\xfe\xd1\xe78;D7\x0f\xf6Q\xf1\xd11\xaa\xb5QC\xc3%\x0d\x0e*E\x82y\xeby}\x83\xa1 \x8dUG?>\xfcI`\xe6>\x06\xc6\xea\xf7'\xca6<\x9e+\x83\xed\x9d\xd3\xc4\xff\x7f\x013IV\xf2g\xd5\xcf\xae\x8fyO\x8e\xfb\x95\x12\xaaQ$WBv\xae\x1c\xdb\x08H v\xee\x85\xa2\xe8[\xfd\xcf\x8f 2\xff+\xfd\xa3\x0c\x8f\xca'\x08\xff\xc3\xb86N\xb8\xdf\x86<\xfa\xff\xfa\x9e\xdb\xc7\xee\xc9\x95\xb6\x1d\xa6\x97\x0d\x872\x94\xffS\xf1\xe5\xa8\x9a\x189\xff\xb3X\x861\xa0\\\x95\xe2\x94\xa3\xfb\xfd\xad\xccdf>\xc3\x04B\x8e~\xb6\xb2\xca\xd5\xcd-\x88\x94t\x16>\xa6W\x90]\xd9\xecp\xa9Pr\x9c\xeeZ[\xb1\xb2'\x9e\xca\xe5\xc8+\xa4\x9d\xc6\x8c\xe2\xb5l\x869]\xef8q\xe3\x82\xec\x82C\xa7\xe9!\x8c\xb6'\x0b\xeb@A\x7fA\xafOu\xff\xd0\xa8\xe4\xaa\n!?\x10M\x7f\\\x85JM\xcd\xad\xcdf\xc7\x9e)\xab\x11\xdf\x95\xcb=\xf5\xd4\xc9w?A\x95N>\xcf\x0f\x96\x83\x9e\xcb\xc2\xbc}\xfajQ\x1a<\xc7\x8fp\xc7\xa0^\xce\xf1\xf2(\x13\xbb\x80}\xbf\xb1\xbd\xbd1\xef\x84+\xbf\x932\x1d\xc7\xe0q\x0bF\xb2\xf74R\xbe\x84\xb4\x17iH\xc4\x8f\x97\xeeIT\xebr8\xd2\x02\xd0\xdf\x0e^\xa7\x99\xda\xf9!gm\xad\xf3\xe4>\xb8\xce\xff\x90\xb4\xce'\xe1\xf7\xc6\xde\xda\xb8h\xd1\xc6E\xfc`\xads\xcc\x8ao\xb9\xe3\xce\xdal\xbe\xf1\x85\xdb\x1e!\x19\xf5(9~\xed\xa2\x0d\x8b\x17o\xd0\xe0\xfe%#\xf0)\xfe~\xc6\x83\xfaj$\xde@\x80\xd5\x94\x88Lp\xbdG\xe5\x1fOa{\xe9\xae\xcd\xdf\xbff\xce\xec\xc3\xa9\x94)\xb0z\xe8\xaa\xd8\x94Y\xd7<\xfe\xf5\xaf\xef\xd8\xf1\xf5\x1d\xfc\xfd\xdb~\xb0\xf9\x9a\xcf^\xf5\x9f\x03\x19c\xe0\xd2\xcb\x1e\x9a\xb7s\xf3\xd0\xde\xeb\xe6\xbd\xba\xe3\x1b\xb7\xde\xfa\x8d\xb2\xfd\xc2\xdd\xb4N\x95RU\xe2\xd0\x04\x9b\xd5R\xd4\x05T\x94Y%8\x1d\xdb\xc0\xad\xa4\xf2K\xccs3\xc3q\xbf\x11d]^\xa9QTb'\x07 \x0b\x9c\xc4z\x1bx\xaf\x07)\xeeH\xb4\x93\x8dF\xd2\xa9P\x84mU\xceZ\xbcjQ&\x9cX\xb9\xf1\xc6\x81\xe5\x0fo\x9f\xdf<0\xb8j\xc9YG\xbc\xb1\x16\x8e\xd4\x05z\xea]\x8a\x87\x05\xfe\xd9$8c\xd6\xda&\xd6h\x14\xe4y\x9f\xdd\xbc\xf5\x9a\xcdw\xce\x9e{\xcb\xea9\x11^\x98\xbc\xe6\xc1sf\xdf\xb9\xe5\x9am[v\xe5\xd5\xc0\x82\x1d\x93\xc3\xd3\xa3!\xc9(Z\xedAs\x8d\xc8\xdb\xa7\xc7\xcey\xc1B\x8a\xbc\xc0\x1b\xfc\x95\x8c\x15\xfa8R\x1ai\xd4\xa3B\xadg6\x1c\x88{\xcbUm\xa6\x92tyW!b\x9ap\xc7\xaed\x0dn\xc5/y\xcc\x82\xe1\xca\xbc@v\xc5\xd3/\xa9\xbb\x90\xd4%\xc7c\xfd\xb9\x97\xf6\xaa\x1b\x9fx\xf1En\x92:\xfc\xe54Y\xc3\xfd\xf5\x1a\xc2\xb2\xbc,yZ-\xe6kr\xb6\x97\xfacH&\xf6\xc7^\xc8\xa9\xcfC\xba'\xc8\xae'^T\x7f\xae\x0e\xc7\xf7\x935\xba\x9c\xee\xf3\xd0\xc7\xea\x98\x14r)(\x8a(I\xe8\xd2J\x99\x1cU\xd7\x1f\x8c&#\x80\xdd\x8c!\x0d\x14+YM.\xffJ\xef\xabEX^|\x82\xc2\xc2\xdeL\x96\x01\xabw@\xb4\x90\xda\xbe\xec\xf2\xa1Zsg\xdfY\xd3\xe6\xb4\xba\x88\x85\x1f\xfc\\\xaa\x00\xd1\xee\xb5\x05x\xea\xd4\x9f\xa0\xb2\xc1\xbf\x19x\xd3\x1b\x84\xb5y\xba\x03\xfd\x97L\xef\xf5Cyo\x99\x85\x92<\xf1Q\xcaO$)\xf7W\x8d6\xa5\x1cm%\xdd\x86\xaer\xdd\x86\xd5d\xf5\x94\x99\x87\xd5\xbd\xd5\xf0\x92\x1f\x90{\xa1\xfcO\x89b\xfe\x8fp\xff\xbb\x08AE\xdc\x80\xca\x8c\xdeg\x0b\xd0\xce\xce\xfd\xb2\x88\xbe\x04\xa4\xa7i\xf2\xef\x89\x90\x9c~\xbaA\xa4\xbc\xa2\x99\xf2\xdfO\"mo*\xee!\x02\x83\xd3[T\xc0\x9c\x8a\x12\x8f\xf2m\xacdH\xd1T1\xd3$\x85\n \xc9\x10P\x16\x19\xd4\x904\x12^\x14\xcc\xfbsfcA\x033\xb7\xdf,\x88\xeaXA\xad\xf2P\x8e\xeab\xe2ks\xee\x90Y\xe0\x86\x8b \x0f\x9ayH\x88h\xfdP\xe4\xcd\x07\xcb\x13\xe2+b\x82W\x90=}\xa5\xd3\xfb;\x01\xbf\xbe\x82\x14\xb5\xa8\"Z&x<\x01S\x1cySV\x14Y\xed\xd6&=\xaa\xfe4\x9f\xbc&\x19\x91\xe81J\xe45u~\x81\xe8,\xd3\xbf\xa4z\xefe\xf9\x96g^QB\\/\xa1P\xca\x84%\x8d+p\x82r\x1fe|Pn\x02\xa5 \xa4T\x92\x86cZ>?\xa2\xe7\xef\x96e\xf2\x9eV\"_[\x91\xe7Q\xa9\x15/\x85\x025Y\x00\xe3\xe1\x13|\x8a\xb1\xe0\x1eqI\xa3\xf6/\\\xa7\xd39\xf6\x96\xd3\xe7\xe3\xe3\xaadi\xb0\xc0EBh$\xaa\x1b\x9d\xe5v\xd2\xf5\xa0\xb1\x80\x85\xd3\x0bwOL\xa4 \x85\xea\xd0\xfafp\x19\x05\x8fa\x0d\xa6,?H\xf3gH\xf9f2\xac\x17\x88\xb5Rb\xee\x85\xb2L\nv >\xdeU\xc0So\x99\x96\xb0^1/,\x9a\x88\x1f\xc4\x93\xa2vc\xab\xb0Y\xf2\x02\xa0Gm\x02\xf4\xc0\xc5\xa8\x90\x17\xd4~\xb8Am\x8d\x12\xeaz\xaa\x0c\xcb?\xc7/\xa6\x92\xff4\xd4\xce\x050\x89\x00\x13\x87yj\x17\xcc\xb8p\xe1k\xb2\xee\x06\x81\xb62\xab\xf6H\n\xab\xc6eE\x80R\xdfb\xe9\xc5\xcf/\"\x1aM\x0d7\xf25u\xb2l\xc2[\x9fdrC\x91&Y\xcd\x90\x17\xdc&I\x9d\n`!>p\xfb\x98;\xa6\xf5\xe5J-\x8fb\x9d\xe0\xc2--.\xe0\xb4V\xe4M\xda\xc54>\xa9\xbcFj\xbf\x96/\xee5\xc0\xba\xce\xcf\x83\xb6\xaf\xa3\xb2\x83\xa2\xdet5}\xc2>C\xfe*\x9b<'\xdf\xf7\x98d\x08\xb5\xe6?,c\xc2\xf8\xbe\xfc\xefd\x8fGf\xeb\xe5\xfc\xbc2\xd2\x810w\x9d\x1a\xe36\xf3\xf3\x19\x98\xf2L\xach\"\xdcf\xf5K\xe4\xa2\xd7\xf2\xff\xce\xb6p;\xd5\xc7\xd5\xc7\xbf\xcf\xb6P\xd5d\xa8c\xff\xa91\xbeEO\x8b\x9a\xd1i\xbe%\xff\xf6\xf7\xc9\xc5\x98(DC\xe4\xe2\xefW\xac\xb7\x89\xaa\xf5V\x08\xe9\x1b2\x9a\x84I)\x88\x9d\x12T\xf6\x14i\xc3M\x9b\xea\xb5\xf8F\x00T\xdbz\xa10\xeb\xc1\xaa\xb5\xf9\x9bU\xaf\xf5 S\xb5\xfe7V\xaf\xff\x01\x0d\x14mB\x1fW6;\x9b\x12n\x1aYZU\xa2zS\x19\x1e\xcfTg>(\x93h\x04\x85\x85\xeeF\"\xe2\x05\x15\xde\xbdT\xeb\xbd\xb7\x8b\xa4\xf1R]\xe7\xdf\xfbL\xdb\xb6\x99|\xa6\xfbLx\x87[\xd5s\x15,\x07'NU|\xae\x80\xaf\xb9\x1a\x07E\xe0<\xf14\x05)\x12\x14\xab\x01R\x96\x8b\x8a\x11\x16\xa0\x0fp\x06\xdf*\x8a\xb8vU#\xa4g\x05\xc4\xc3*\xf1g\x98\xf2\xb7j\xc9\x99*=\x81~\xdc\x83\xa8\xec\x11A\x89S\xdc\xfd\xc4\x93\xce\x10\xcd\xeeA\x0cJ\x82Hw\xe43@Nur\xaebw\x99\xb0\x8d\xc8\x80\x7f\xca\x8cx\xc0}[\x83`\xf07\xba\xbd\x92\x8b\xf8\xa4Z\xa7\xcb\xca\x12\x9btPlh \xd5\x04\x13\xb3\xa6L.)NU\x82}\xbf\xa5\xa1kq\xdc'\xd8\xddv\xc5\xe9\xf5\x88FQr\xd7\xb7\xfa\x8c\x0e{\xcb\xa4\xf3S]\xf3Z\xebL\xf9\xff(\xd7@\xe3*\xfaSf\xc2\x1e^\x82\x96+u\xf6Pe_k#\x8e\xf1\x95\x19.\xc98\xe9\xce\xc9\x82\x05%\x8d\x90\x05\xd5\xa0\xaf,\x81\x85\xaa@\x95\x9b\xa3TK\xa3\xa4\x07\xd1\x85\xba\xa7\x1a\x9f\nt`\x91\xdf\x91\x88X\xd4AD;\xa6\x82\x1ab\x86\xa4\x81|p\x15\xdfA\xba\xe27\xf0}q\x07\x15\xd2\x15\xbf\xe9\x042\n@Y\xfb`\x1d\xdd\x07~\xa5\xee\xc1\xb5\x14\xb6\x8a\x88\x17i\xd4\xacK\xbd\xfb0j\x9f\xf7\xd2Y\xd5\x11(\x0d\x9e\xf8\xdbR\x84\xfa\xc3\xd3~^\x88\xa8\xd2\xa7\x188\x83>\x85\xe8=\xe3F\"\x9a\xcb\x9cA[\xe5\x8b\xd3Dq\xfbvQ\x9c\x06C\x02\xee\x8aX\xf5|Z\xf5\x8bsO\xf7\x85\xfe \\\xe4/\xcdf.\xc1\xd9\xd5\xe4\xb3F;\x04\xcc\xe6\xffk\xe1\x1aP\xf1\x95\xecb\x87d\xb3z7\xd4\x90e\xcd\xb6-6\x8bb\xb2y\xb6\xd8\xccb\xc0aWjnh7Y\xf4L\x0f\xe1F\xfb!\xbd4\x83\xc0w\xdf\xe2ssF\x8fC\xban\x8fh\x96\xcc_0\xf3\xfb\x1f\x85\x92>\x0b\xe1\xb1M\x05\xbdZ\xb2\xab \x1f\xb0\xf2\x87\x80\xefnC\xed\x7f\x9c\x8c\x0c\xac\xc4\xc3*\x1a\x11#\x125/O\xf6\x02U\x03\x7f\xd1N\\(3\x06o\xc4@\x85[\x12\x0f7\x0f`\x8bMg8x\xcf\xdfg\xace;f\\y\xf1\xbd\x97|f\xd6\xa4\xa9\x0e\xde\x91\xa8\xdb]\xebi5\xae\xa8q5q&\xd6>\xb9'\xba\xf4\xe2\xf3\xef\xbc\xe1\xe5\xb0\xd1\xdf\x18\xd9353\xe9\xfck\xcfY\xea\xad\x91\x9c\x1d\x01\xdf=W\x9f7\xe7\xe2+\xce\x8byx\xfeI\xcee<\xac\xbe\x93\xfb\xc2P\x8f\xc3h\xb1X a\xeb\xeav\xd7\xb8\x82\xd3\"\xc6\xf9\x8acJc\xfa\xc2\x9bo\x1fH\xccO\x86Cu]\xb3L5\x91\xae\xab\x03\x81\x86\xd4\xd2\xc5k\x93\x93\xa6\xf0\xd1\x96\x86\xf3\xa6\xf5\x84\xa7]x\xf3\x8a\xb8\x1b\xe6\x8a\x0b\x98\x06~\x13\xff#\xaa;!\x91\x06\xde\xdb)B5\x1a8\xa8\x04/\x1aP\xac\x05\xed\x0d\xf5\xf5H\x1c\x9a\xd1F#0\x89\x18\x1a\xb0B(\xf4\xcap\xec}\xd1Fst\xd2\xdc\x19M|\x9d\xb9\xc6l\xe7\x88\xc9)]t\xcf\xbc&\x83\xdd\x96\x99\xbf,\xe3\x99\x97nt\x1a,\xb6h[\xd0\xe4Y4\xdd\xac$\x17\x9ewQ\xd7\x92\xb5,\xcb\x0b\x9e@\x7f\x8b\xd1\xe0\x8f\xc6k\x1a\xe5\x9a`D\x94\x83g]r\x0e\xff\xa3\x99\xb7|\xea\xfcY}\xcdVq\x92wRC*\xd4\x13\x8e9[o\xbb\xff\xa9\x07\xe7\xa7\xd7\xce\x9d\xdcd\xf0X\x0c6\x8e\x17\x9a&\xcd=\xff\xe2\xcd}\x97\xed\xdf\xb0\xc0/*\xcd\x8f\\\x00\x04\xcb\x94)\xb3\x83\xc95gO\xf2\x98l\x9d\xd3\xa6\xaf\x08\xac\xd8}\xd9\xd91:>O\xfd\x8aY\xc7\x8f\xf2s(\x95p6\x1d\x9f\x82[\x12\x82\x9dB/t\xe7\x88\x81*\xcc\xa0-n:\x15\x11\xb1\x01\xbd\x0d<\xd0\xa6\xf0\x14\x8d\x08\xf8\xe8)\xc8\xfa\x10\x0b\xac\xe1+\x8f\xde\xb0~q_}\xfd\xe4\xc5\xeboxt\x0f>L\xae\xaf\xef\x83\x07V\x96\x0dF\xdf\xc8\xdfG\xbc@d\xce9\xd7\xc6[<\xf1s/\xbc\xed\xae\xdb.<7\xee\xb1\xf0\xd6s\xf3\xa7B\xb2\xc9\x14\x9ed\xef\x90B\x12'\xb7wX\x82\xfc\x9c\x8e\xb3\xce\xbf\xe4\xfc\xb3Z\xe9\xb5\xa3\xfc\xe1W\xb2\xc1\xd5\x97\xd9>2\xb2\xbd?\xed2\xc8\xb3\xaf\xb1\xf78\x9b\xe7\xac\x9e\xd5\xd3={\xf5\xecfg\x8fcsC\xb3\xdc\xe5\x9c\xd5m\xe3\xe5\xa0\x1c\x96\xdb\xcfr\xe2\xbe\x0e\x0f\xf5e\xa0\xbe#\x8c\x9b\x89\x02E>\x88\xf2\xfc45\xb5\x14\x12qo:\xe1J\xa3\x14\x16\xd6\x04\xec\xbcX\xab\xb0^io\xba\x93P,x\x8b\xb5f\xb5:/y\xa0\xf1\xbc\xafn9\xa7\x9dV\xf3\xd1\xa5S\xa77=\x10\xe9\xba\xf2\xee\xe8\x92u\x0f-\xed\\\xb8%\x02\x95K\xe5\xcf\xa6Uv\xb6\xce\x1b\xbc,\x19\xbb\xe2\xb3\x80\x84\xed\xc5\xeaZ=\x1c\xd6v\x9b\xfb\xe2k\xaf\xbf\xa4N\xd1*+_\xa7.\xfd\xda\x8a\x9f\xf5\xd6\x9e\xbbi\xfd\x9a\xda\x83=w\x0d@\xa5\xe6l\xa2\x15m\x98r\xf6\xf4>\xdb\x17\x9dO\xad\xc7\xcao,V\xd4\xb2\x92\xd7\xeb\xc9\x9dz\x0c&:'\xff4\xf0\xce5\xa8\xd3\x1a\x85!\xea\xd59\xe8pI 0@I[\xcdP\x1eU\"\"\xa9s\xd9\x1d\xeeInv\x87R\x17>\xf1A\xb8\x8e\x98\xc99t\xe6$\xe7\xa83/\xab\x9a\x7f\xb3|k\xa3\x108y\xb4i\xee\xac\x9d\x9aE\x0d\xfb\x93\xdf\xf8\xddc8\xf3\xc2E\xd7!Q\xe8\\\xdb\x82}\x0b%A\x9a\x81f4\xec\xa0s*\xaeA8\x8d\xa6\x1d\x82A\xb3\xd8\x04\xce\x80\x1d\xdc>D\xae\x90=5\x0euw\xb6\xd6\xf5\xc3\x1f\xbaj\xb3\xeanG\x0d\x00z\x05?2\x94Q\x0f\xaa/I=\xee\x98\xdbf\xfdH\xfd\xe8\x02\xf74\xc5n\xba\xe5\x16\x93]\x99\xe6\xbe\x80\x88\x1fYm\xf0\xaaG\"\xb3\xc92\xe4P\x1cE\xddH\x7f\x99\xcdf\xb9v\x14Zn\x9e\x07<\xc2\x9a\x02\x97PiA_\xd2q/\xb3\x8eP\x12\xc9D\xd5\xbf\xf0 \xe3\xa8$$\x8e\x1b\x1d~%Nyhr\xdcOdM\\\x91-\xfe\x8cm\x9f(\x88\xe4@\\\xb3\xba\x8f#\xbd\x84\x06\xd4\xea\xc6\xbc\x93\xd2N\xef\xe7J\x9fO\x1c\xd4\xe5\xe3>a+\xff \xb5uJ\x17\xa8\x04*(%\x81\xc2\xa2FP\x84J\xc4\x02W\x94\x08\x94\xa5\x8a\xa6\xbd\xf8\x96\xdf\xf0\x91,\x7f$)\x8f\xe7\xf7\x01)\x07\xe5\xff\x98\x1d\xfa\xb3\x92\xff\xea}\xd7\xff\x98\n\x0eB\\\xad\x96\xe0\xcf_\xbb\xef\xfa\xc7\x15\xfe\xbew\xa5V\xe9] 0\x86\xd1T\x13\xa5OC\xc3\x8aQ}\xe8\xbe\xeb5\xb1\xd0\xc2\xe2{H\x0fo*\xe4\x99\x15;;\x04\xf5\xe8\x91\x9e\xc9r\xc7\xa8\xe2\xea\x01\xf5M\xd4c\xe5\x075\xad\x14\xdc\xe3\xd14S\n: \xb4\xfdM\x8c\x8b\xee\xe6\x16\x9b7\x90(kY:\xeb\x01\xa9\xaa\xb8\x95z\xd2`\x88gp\x0d\x9bJ\x86st\xcb\x89\xfd\xb1v'\xb2\xa1\xa6e\xf0\xd2G^~\xe4\xd2\xc1\x96\x1a\x03i\xe7D\x9b\xbb1\x9a\x9a\x91\x8a6\xbadA \xd8@'N \x02\xf0\x8a\xe6\x15\xb1\xb3\xd6\xadN.\xd6\xf4?\xcef\xb2\xc2\x85\xdc1\x98\xf3b\x05\x1a\x95\x8ezJ\xfd\xa1\xb1D \xec\xa5V\n\x01o@7R@6\x8a<\xc0\xfe\x01%IF\xa9\xd80\xeamj=\x0d\x90[\x7f\x8e}N\x7f\x89\xe2\xd2\xfc\xdb\x8a\xa457\xb9\xff\x1bp\x05\xf2\x05\xa9y\x8c\xc4v4@\x1b<\x06m\xd0\xad\xe1\xbf\x11\xc1\x109T\xc5\xf2\x06p?\x8d\xda\x03R7\x1d\xfa\x9d\xfa\xa5\x01\x8a0\xd2\x9b\x9a\xb4\xdaQ\xcfG\xb8[j\x1a\x84\xac\xd0\x1e\xc8\xdf\xd9\xcdzi\xdf\xf7\xb7b\x93\xb4\xfa\x1b\x9d~\x83\xf0/)wC\x03?\xe2\xb1\xef \xd7\xa8a\xa5-\x07/\x8aC\x04\xaen\x93\x99\xfb.\xc4\x95\xdbH\x0cj63\xa8\x80\x92\xd0\x04\xb8\x8a\x10p\x04\xf8\x91\x93Krh\x12\x14\xeb\xcf\xcf\xc2\x07\xeeX\x96\xeaI\xe7\xc6\x8ej\xdf\n\xbf\x82o\xad\xe81\xc1\xc59\n\x9f\x06\x14\x01f\xd4\\\x8e~\xda:\x19-\xa6\xd4\xd1\x93K\xa0\x8f4\xa9\x1b\xb17B\x06Y\xcd\xf6\x89\xcc\x86\x8ey\x05\x7f\x08%\x9bDC~e\x93\xe8m\xc0\xde@\xd1]\xd1\x08\xfa\x03\xff%\xc0r\xfe\xa9\x02\xd6\xd9s4T\x03\xae \x99\xc5\x1f\xe2\xae\xd0\xf3\xd6G-\xe2Ug\x90\xf5>\xcf\xed\xfbH\x82Op\x07V\xd6B\xec\x90\xc2]\xf4{9&\xff^6\xb9\x1f|\xd0m\x92\xf5\x07\xe5\x0b_PLLI7\x02\xc7\x92\xa6i\xca\x10\xae\x13\xf5\xe9\x0c\"'T \x14\x05}\xc6\xe3\xef? 4\xbb\xf3\x17\xb9\x9b\x85\x03|\x87\xa6[F\xc7\xad\xfat\x16u/\xd9_y;Z\x94\xbc?\xdb\x1f\xa3H\x86K\xae0W\x9dz\xa4\xe8c#\xa4\xd9\xd9\xd0)\x80\x8e~.\x1cr\xc1\x8a\x16\xc4\xa5+\xcaB\x89\xb0\x8a\x03\xb1\x1e&J\xb0\x93\x83G\xa00\xf9\xcb[\xfd\xd0\xe4\xd9\xfc\x05\x91.\xce\xa1\x08\xecr\xb7\x9fO\xb3\x16k\x8e\xdd;VC\x95\x89\xa0oX\xa8 \xfa\x19\xcd\xf6K\x19\xdb\x9dS\xdf\xb3\x1b\xeb\x15r\xb6t\x82\xe5\xed\xb2\xed\x84:z\x82X\\\xb1\xfaxm\x8b\xdbJh\xff\x99\x0fx\xb8\x14\xf0\xd0N\xf7\xc7h\xdb5\x10\xaf\x0b\xa5K\xe8`\x85\x0f\x05;yd\x03p.Ec\x9b4\xb2X\x9eD<-\x01\xb4ll\xb5\xdbip.\xbb^\x1e\xd8\xe2p\xd5\xd7:\x8d\x0d\xd9u\x8f/\xee\xbb\xf6\xfc\x15\x99.\xab\xc5Y[\xefrl\x19\x90\xaf_\xe64\xb8\x9a\xe3\xbd\xc9\x1ekz\xce$~Dq\x85]7/T_<\xe8\x8f\xb5\x88\xbc\xa5\xde\xe34K\x0e\xa7$\xf0\xc6\x96\x98\xff \x99\xbb\xf0&w\x93\xab\xf6\xe4\xb7\x0d\x86\x9e\xa9S\xa1\x1f\xb8\x197\xff\x08\xff\x08\xb5|K\x8b^\xfc\x8d\x8a\xf8\x9b\x8e\xe2\xaf7\xedMsMG\x17\xfd\xe1\xf9\xe7\xff\xb0\xe8h\xc7\xc3\x0fw\x94\x85\xb9\xc3\xe3\xa2\xb40]?\xb2\xb4\x0f\x04\x98\x0efja\xcd\x145a\x04\x8ei\x8d\x96\xd0\xa6\xe8\x016C\xbc2\xf4no\xc2\x95\x0c\xa4\x93\xd5f\xa0\xec=\xf1\x96)\xf5d^\xcb\x14\xff\xfb\xf6v\xef qNc\xe3\xd4\x8e\xb4\xfb\xfe\x8bl=u\xd9\xe1\xec]?;\xa1f\xe2\xf9-E\xd5\x02~\xe4\xec\xf6\xe1\x1b\xcfn\xcfv\xf8\xd5}5\x81\xb8\xcf\xd7\x1c%\xbb\x9a\xeb\xbe\xf7\xfd\xfa\x96\xec\xe8O\xd5\xbb\xb3d\xeb\x8d\xbf=\x84Z\x02%\x01v\xb9\x8e\xe8 \xd3\x04\xb3\xd0\x14\x0dn\xafK\x97\xa0\x14u \xd0\xcc\x93*J\xa6\x84\xea\x9d#1\xe4h\x84u1\x1aHr\xec\xd0 o\xbb\xfd}\xff\x94\x16\xf5\x1b\xf5SZ\xe2u=\xb6\x8b\xeew\xa7;\xa6n\xcf\x97\x14U\xd8\x0b\xef\x82\x1a\xc4\xe3\xe4\x95\x13\xfc`\xa0F\xdd\xe7\xef\xc8\xb6\x9f\xbdE\x1cn?\xbb\xa5\xfe\xfb\xdf\xabk&\xbb\xa2\xcd\xd9l9\xa0Y\xf5\xee\x9f\x8e\x1e\xfa\xed\x8dd\xab\x86gA\xe2\x17\xc38NS\x0fG\xe1\x14\xea\xb3\xcaD\x9f09M\x91\x15AK{\x1d\xde\x80K3\xdd\x8a\x84\x02\xad\x1c\xaa\x10\x00[_]\x05\x92%W4z\xd6\xdb\x88u9\xe9\\~\xe5\xfa\xe5\xebn3\xd4\xc9\xea~\xf1\xc9zir\x96\x84\xf1\xe9\x0d\xc5\xe5\xf4\xa8\x93X3k\xe2`Ps\xc4\xea\xf8\xdc\xca\xfc\xe2\x92n\xc7\xe5\xef\xda=\x1bm\x11\xf9\xba\xc1]\x8b\xd4\x83J\xcb\x1e\x1bks\x84\xcd\xf3T\xd39d\x99\xd2\x02\xf5eYN`}\x9e\xaf/\xfb]U#\x14\xc6\xf3b\x98;R\xcc\x1c\xa8\x93\xd0\xc0\x17t,\xa2\xdal\x9f\x08h*\xf6\xa2\xd7#JB+\x1b\n(\xb4\xa1\x02iGx\\}~I\xd6\xb3F\xb7\xddv@T\xf7\xcbu\x86\xdb\xd6\xad\xb8\xeaJ\xa8\xda\n\x0b\xb1\xad\xf7\xcc\xff\x9c\xc3\n\x90@-L\x9c\x99\xa8\xe1w\xe4z\xc3\x0e\x12Y\xa7\xeeg\x97\x94\xfa\xd3\xe2w\x89`wx-\xf9\xbf\xd8\xf6\xb4(d\xd9\xa2]\x83\xd7\xc9\x11\xdbF\xcf3_\xf7\xf8X\x81cY\x92mQ\xd4\x83\xe7\x90\x0f\xdf\x1bW\x1f\xe6b\xa4-\x04\xa9\xd0F\x0c\x0e\x02\xa1\x81\x14\xea\x04K\x18\xf55\xd5\x08d-0b\x11\x83\xe2\xa8\xe7\x90\x83\x04\xc2\x97\xd6\xa8\x93T+\xe6\x91_\xefZ\x84x\xdcc\xcb\xff\x05\xd0j*`\xfb\xfb\xe5\x88}\x8f|x\x0e\xe2~\xb8L\xc7F\x90*\xdaS*o\xea\x9fM\xd8\xaa\xeaA\xad\xcd\xf3\x96\xb2\xfd\x1c\xeeT\x9e1p\xc7\x047\xb51?\x8bR\x0ct>\x0f\xe9\xf3\xbb\xb6R'\x1d\"\xfa\x90\x8b\xc0\xe4\xc6\x17\x14\xc1E\xc2y\xd3)o\x83P\x8f\x067\x9e\x94\xe6\x82\xc5\x11%\xab\xcb\xc0$r\x11\xc3v\x1d\xf5\xac\x0dQ\x9f\xbf\xfb\xbdeE\x94\xc7\xe3\xd8\x16\xe7\x94+\x06\x8d\xbd\xbbn\xf9zl\xdd\xe5Vl\xddFr\x05kt\xc9\xd6'\xb5\xa6'?R\x0f\xae\x84\x06'Z\x83CE\xd5I\x1e\xa7Ky\x03\xbb\x05 ga\xce\xf60\x1e\xfe\x8b\xfc\x17\xa1^\xe1\xea}\xa0p\x04E;\x85\xf5Kq{\xd2\xe1T/\xf9?\xefi\"%\xed\xc6\xde1\xce\xde\x92\xffb\xf1-\xde\xd4\xbeq\xc6\x9b\xcc\x19\xcb\xb5\x11\x83\xdb+ \xa2\x8a8\xc6]\xc0\xcarI\xb8\xdc\xfa\x94\xda\xa3V\x95{\xacd\xc8\xaa\x17\xcd\x9c\xb9\\\xe8\x95A\xcd\xf4\xd3Q\xd0vO\xc4S\xd5\xf5]0.\xdb\xea\xfaN\x03\xa8\xec\x15X9s\xb9\x02\xd5v\xa1b?O\x1cE~\xdaFPU}\x1f\x1co\x9e[Y\xeeK\x13\x19\xe5r\xc0\xe9\xd6\xf0\x0f\xf1\x0fA\xb9\xc3\xcc\x93U%\x87\x81\xa77D\x80w\x17\x0d\x1e\xfd\xea\xf6\x88q\xd4\x0bb\xe1/\xed\x91h\xc8\x0d\xed\xe1A\xd9\x14\x1a\xb1\x91hPbQ\xd8\x93JB8\xd5I\x0c\xba\xe4\x07?\xe1\x1aI\x06%=\x04\xc5X\x91t\xdc\x13O\xa5;\xb9(P\x1d\x91h\x03\xbaL\xecd\xa3\x06\xd1\x0dS\x01\x04 \x95'\x0eh\xff\xdd\xb1\x9f>|\xfe\xf9\x0f\xffT\xbb\x91\xac\xdcV?\xd9,O\x95\xdd\x03\x1c\xe7\"\\\x8f`\xaa7\x04\x89\xd5\xe3\x13\xed\xc1.\x8b2\xd0\xe7\x17\xdd>\xce\xe6\x0e\xb9D\xe1\xb2\xcd\x0d\x81f\xce\xd6m\x95g;\x9c\x9d-\xed\xf6\x84\xcc\x13C\x8c'\x9c\xa5\xd6\xe9u\xb9,\x06\xbb\xa1\xa5\xce z\x14\x97A`-\x02\xc7\xd9\xbc\xbc\xc1$\xd6x\x0cvc\x93\xc3k2\xb7\x06\xa6[x\x96p\\c\xdab\x15\xfc\xed\x93l\xce\x80\xddi\x1ch\xb5s\xb5\x9c\xd9iv\xf0\x0f\x15a\xc3\x9b\xc3\xea\x10M,g\x10\xc4\xa8l\xf1\x8a\xc1M\x9e\xe0\x96z\xd3\xdc\x1a\xb3\x9b7Jv\xde\xd4\xd9\xc0\xcb\x91V\x87RW\xcf\x8bN\xb3\x95\xdd\xe4o\xce4\x19\x89(\xda-\x84\xb5XB^\xd2Cl&Vn\xf4\xb1n\x9f\xbf\xbe\xc1n D4[k\x1c6\x9e\xb3\x86\x9b\xecN\x8f\xd7&\xb5\xba}f\xa7\x933Y\xbcQw\xd0@$\x93U$(\xc7\xaao\xb6:-\xfcZG\xbc\x85#&\x8b\xc5\x12\x86/\x1d\x85}\x0b\x96?\xc4\xdfN}\xc6\xa5\xbc\x827\xedA!M\xb4\xe0\xfc\x04\x08h\xf6\xf8W>\xa3\xe6\xef?iX\xb2p\xca\x1d\xfd\xf9\x03r\x9b\xbcA\x96\xd9\xa1\xe0b\xfe\xf6\xf3?u\xcf\xb1\x9b\xce\xb9\xb3-h\xf1\xe4\x0f\xd8\xed\xeb\xe56;\xbb\xeaS\xffB\xf5#/\x82\xb5\xe9@\xd1\xbf\x13J \xc6\xe9\xfe\n!%Q\xad\x08)\x04\x94\xc0Dq:{JI^\xde\x91\xcb\xa1\xf5PY\x04\x1a7UG\x01\xe7\xca\x1f(\x11\xc2\xc0\xbc\x9f\xf6\xa1h\xb3?Hm\xff\x1d\x1a\xac\x1a\x04\xc8\xd1\x8a\x0e\x12\x18\xe6vRE\x88\xedH\x8e\xf4\xe7\xd4=\xdcN`P)Q\x9c\x9f\xa5\x8e\xe6\x80G9\xae\xd3F\x1aM\x87\xd6S\xe1\x02MG\xa7\xf5@2\xa4\x04\x1cE\x1f\x11\x89$Q\n\xb5$\xc7s\xb1~\xe4\x92TkN\xb5\"\xd7\x03\x1c\x0e9\xae\xd5\x86\x1f\x018\xfbc\xeaF\xa4\xf1\x01^\xea\x10\"?+G\xd9\xa0\n^\x02\xf7*\xa6\x17\xbcgUlFVx\x8d\xaa\xdaU\x99poC\xa8\xb0\x9e.XC\xc6\xb5\x8d\x8a\xd7\xb5\xcd\x89\xd7q\xef\x82K\xea[\x1b\xafk[\x1b\xaf\xe3\xf6K\x97\x1e(l\x81\xc0;\xf6\x0d\xba\xd3\xa1\xedn\xe8\x19\x00%^\xf1\x9dR\xd4j\xad,$\x1f)\x16\xa7\x14 \xf8\xb7\xca\xec1\x8b\x82n.\xbf\x8f\xdfG\xf7:C\xd0\xeff\x8e\xd3\x16(\xdf\xf1,\x98\xed\xd0;\x9a\x84\x17\xc4\xb4\xa9\x01\xf4R\xc2\x97\xbfF\xeb\x9e_~\xf0\xce\xe3\x17^\xf8\xf8;\x1f\xbc\xf3\xa5\xd5\xab\xbfD\xbe\x7f\xf4;\x1b6|\x07/jGGSSG\x13\x19\x84\x9bG\x92\xd3\x8e\xc4\xbcD\xac\xf1zbR\xef\xa4/X?\xbd\xf1\xfb\x8a\x1f\xc3\xed\xf1U\xda\xc7p14u\x04\x02\x98$`\xbe\xdf[\xdf\x9cH47\xf5\x087\x11I\xf2~\xa5\x89~I\xff\x18r\xea\xdf\x99s\xf9\x17\xf9#\xe8\x9f6\x8c\xdb+\x91h\x84\xba\x15e\x80W\xf26@wK\x93\x14\xcc\xb8h6,\x12 \x871C\xb5\"\xe0\x9d\x17\x87\xb7\xe6\xa9\x16\xda=\xadm\xce\xe8\xf1\x90\x14e\xb0A\xf2\xd3\xf3\x8c\xe2\x96\x0b=\xbe\xe0\xf4\xee\x81@\x93z\x97\xdc\xd0\xd0\xe1\xb2 \xa6s\xd2\xf3\x13ls\xb3]\xf4;kkl\xb5\xea\xd3r\xac^\"s\x83\xa1\xe9\x9d\x92\xdc>\xd5&\xd5\x84\xac-[\xd7\xdf{\xc5Ji\xd2\xb49[\x82\xdd\xb5\xb3\xc8\xa9\xb9-\xe7]\xb1d\xde\xa2\xb5\xb2c\xd2\x0c\xb5An\xb5\xdb\xb9\x83\xe4g\xe7}\xea\x92\x87\x1d\xbc\xbb6\x1ehT\xef\x96\xeb\xfc\xc9\x96\xb4?3\x03s\x8f\xda\xdd^k\xad\xfa\x8cL\xeac\x12Y\x18\x0c\x05\x881\x1d\xebZ\x13\xb2\xb4n[\x7f\xf7\xa5\x83b\xdd\xb4\xbeE\xdf\x86\x8c\xe7\xd5\xa4\x03\xcdw\xac\xba\xe0k3\xd4f\x99\x95\xe5\x88>\x86\x0b\xfe\xfffM\xe4\x01\x10\xd5D\x82\xe8\x85\xd5\xa0\xb8a\xe5\xf1\x14D\xf0\xe9\x0c\x8f~}&\xf6\x0f\x08\xac\xc1@\xbc\xa35\x10\x8du\x0c\x04gn\xa8\x9b\x1eO\xc8\xa2<\xb9\xad'`\x0b&b\xd3\xac\xbc\xb1-6\xe0\xf7\xae;\x83\x1f\xc1\x0eX\xf7\"\x91d*\xb2a\xa1w\xd2\xfc\xde\x1eY\x94\xa6\xb4v\xd6\xd4t\xb7L\xb3\xf0\xa6X\xeb\xac\xd6\xb8k\xf1U\x00\x7f\xdf\xa9\x0f\xf8\xad\xfc\xb7a\xee\xe8\xd4=HR_\xc3@\x1d\xa6\xa3\xc4+j\x932\x97\xf6T*\x89\xc2\xa3\xe8%\xec\xd3/\xcd\xb8o\xc6\xa4\xa0\xbf\xb1\xd3y\xe1\x87\xea\x0d\xa3\x97\xbb\xee\x9b1\x83\xd49/7\x9b \xa0\xfe~\xc67\xe1\xfd\x8c\xb4\x1f_\x93\xdb\xf9o\xc3\xd3\xea\xd6+\x82\xfe$D\xfc\x1d\xd2\xafs\xde\x07IH\x9d:\xe7r\xa3 \x83\xf0 \xa4yiF:\xdd\xe5\xb8\xf0\xef\xe4v\x8d\xf7\xcb\x15\xfd\xc0(\x8c\xbfd\x13\xaeO\x1e\x19\":\x02\x0e\xa6\xa0om\xd8\xff\xc5\xecdM\x948\xe5\xd2\x0c;\xa4\x9eZ9u\xea\xca\xa9\xfcHCg\\\x19\x9bK\x05\x18/*\x89\x8e\xfd\xd4\x99\x8dg*\xbe-\xf3I\xe8\xd1\xf6\x97\xb1\xa2\x04\x88_\xc1E\xa2\x01\x9c\x8bRq\xee\x0eR'\xfb[\xa5f\xf5?G\xd5\x7fU\x8f\xbdA\x12o\x91vb A$\xffe\xf5]\xb9\xd5/\x87\xd4\xbf\xaa\xa3o\xa9?|\x83\xd4\x90\xdeQ\xe2m\x964\x99\x15G\xa2\x8c\x837\xf1G\x9983\x8d\xda3+\x0d\xbc7\x044\x87\x03z\x04*\x0f)\xa1$\xdd\x8bJ\xc0\xd8pD\xb5\xee\x93N\xfa\x08j\x195p\xd0q\x1c\x19\xbe\xb7\x93e\x8fDf/\x9d\xd2\xce>\xce\xdb\xfc\x89\xe8\xb4\xe0\x94%\xe9\x96\xc3\x0fg\x87W\xb5\xf8\xb8{\x85U\xf3\xeb:g,\xean\x8a\xaf\xb8l\xb2\xbf\xb5U\x91\\\x11\x9f\xcft\x99'\xd6\x13\xac\xf1%\xd2\xfc\xd1E\x82\xab}\xe0\xf2\x19\xcd\x9d\xedu\xa2\xfaC\x9b\xe8\xea\x98\x92\xcd\xdc\xbb\xdf\xbap\xb1}U\xcb\x15+\x17^b'\x8b\x8d\x92\xaf\xabo(5g\xe3\xbcV\xc3B\xd5I\x9c\xbc\xe4OE\xfcm>\xb7\xd1\xc0\xbd\xa9\xfe\x805y\x9azg\xf6\x86}\xfa\x1e\xc1\xa5\xdc\x03\xfcA\x94\xa9P-\xf8P/\xfa\x0f\x80\x11\x8f\xde\xab\x00\xec\x84\x12\xf2\xa0\xd56\xcc\x07)\x14\xa1x5/\x03t;1\x9a\x11p\x931\x94L\xa0\xba9\xf5A\xdc\xb3|\xf7\xea\xdd\xd1)\xfd\xb5\xe1\xe5\xeeX]m\x8d\x81\xfb\xf3kFE\xe9H\x05/\xf14}:\xb8,\x19oLM\xaao\xf2\xae\xbb6\x12]Y\xe3M\xf35\xa2\xcb\xea0u[\x9b\xdfy\xd2\xab\x88fV\xeah\xbe\x98?\xb8\xe4\xdeE-\x03A\xa7_i\xef\xab\x9d\xdf\xddj\x12\xb2\xf1\x1d\x0d\x19\xd4.\n6|\xde\xe55\x92`#\xcf\xd5Z-\xf7sv\xc1fq\x98\xd3\x9f\x9d\x9b\xed\xeas\xb7\xcd\x9a>\x18\x18\xa2\xe3\xdaw\xea\x14\xff\xa0\xee7C\x97\x11\x15\xe5{ A\x93\xfa\x85\x8a\xd2\xd6]\x15B\xbe\x1c\xeb\xd5\xeez,i\xf7H'd\xf9\x84\xe4\xe1v\xda?\x92`E\x87\x95\x9d\n\xfcx,\x87\xf6m\xb1\xb8z\x87`\xcdF[\xef\xea2a\xf5v\x89hp\x99\x0e%\x03(\xd4\xcc\x92\xf6\xfc\xbe\xca\x82\xc9\xfd\xd95\xd4\xa6;G\xda\xd1\x8e\x1bh\x94\xed\xa5\xb2\xb3\xb9\\\xdey\";|\"\xab\xd9\x9d\x16\xca\x96\xa9\x9drx\x82z\x16\xcbs\xe8P\x89HCT\xd7v\xa8P$\x85\xe9\xf5ly}\x87iyhvM\x8eC\xf9\x85r)\xdd#\xc3x\xae\x9b\x08\xbf\x04-\xdc\x13.(\xf3t%fu\xbb\xf4\xca\xc2\x80(\xdb\x85e\xc1\x95\x16UU\x96o\xe2\xb2\n\xa5p\xb4\xd4qe\x1d\xd1\xcb\xa1\xe5\x95\x97\xa5\x15s\xf2y\xb8i\xba X\x96\xe6k\xa5`\xc9>\x1e\xa3X\xaf@2P\xf8\xaf.\x0d\xa82\xcd\x8c>\xabn\x84|\x91\xca,/4\x97\xa3\xd4\x1a\xfe}\xc2\xf2\xa0\x0c\xae\xf0?A\xed\xb8&\xcdJ\x9f\x16\x86\xc5\xe6r\xa7+\x8f\xad\xf0\xc3\xc9\x90\x8f\xf1\x1dCV\x93]{\x8e\xe8\x16\x17\xecZ\xcd0\x00- \xfa\xf9A=\x96\x1a\x08\xe4\nF\x03\xf8\xae$\xeb+\x94\xd3\xf6\xf1%U\xb8\x15Z\x8dy\xa2\xad\xc2\xde\x97\x8e\xb0\xd9\xb2R\xd5\x0d\x05\xb7B\x83\xba)\x03\x14\xbf\xf7\xa5\x8a\xe2wT8\x16\xfa\x1f\xc1\x12(\xe1\x1fa\xd9\xfbR\xc1\xce\xa3\x1c\x03*-\xc0\xaa\x97\xc6\x0f\x1e\xd9s\x1a\x80r5v\x0d\xea\xff!^tZ:\x15/\xc7K\x15,'\xb1\xc2\xeaF\x0d\x1e\x0d9\x80\xbb=\xe3\xda\xe6G\x88<\x00\xa7\xb8\x07C\xed\xd1\x1au\x1b\x93\"$\xba-\xbe\xee\xb2F\xf7\xf3S2\xe7(\xf3\x17\xc9F\n0Q\xa9\xdc+X\x90\x9a\x81\xf0w\xc8,\xbb]=b\xf7h[q\x9eB\x8bQI\x92\x06\x0c\x0d\xfe\xa7\xfa;)\"\xc1\xc5\x8c\x9a\xd39\xdc\xd22\xe3\x9a\xf46\xc3r?\xe7\x1f\xd3}l\x8a\x06V\x0c\xc7=b\x10\xb8[\x98\xb5\xa3\x11j\xaf\x1e\x08\xa24\x80Az\x94\xf3\x99\x8c\x1c\xf7\x10K\xdak\x1c\x12Q?T\xff\xc2[%\x93\xc9$\xb0K\xa2Q\xf5-\xaf\xd1l_@l/ &;\xff\x98\xc9\xec\xb0\xa8\xcbD\x12r\xaa?P_\x13d\xa3E1\xfd~\xfdz\x97\xe2^I\xba~b\xb0\x17\xf7\xa7\xd4r\xdc\xe8\xbce\xa1u\x8a\xbcf\xb9\xadP\x95/\xcd\xd5\xba#\xdc\x0cE\xff+\x9aS\\\xecG\x7f\x1e\x87\x1c\x1d-\xd8R4\xa8\x8d\xab \x91S\xae\xf3\xd6S\xae\xf3V\xe4\xbf\x91;\x0b\x9d\xce\xc8*\x11`\xdfG\xb8\x14\xe9*5'\xc7\xe4\xfbd\x99L\xba\n\x98\xaf\xff~\xa4\xda\xc6\xea \xe0\x855\xaf\x94F\x9a\x18\xd2\xc6hb`\xa0\n\xbd\xea\x81\x9c\xfa\xb3\xc24\x80\xfd[b$~\x0f\xbfG\xe7\xa3N\xcfA\x15X$\xf2\xdb\xf7\xdf~\xf4\x82\x0b\x1e}[\xbb\x91W\xdf}\xe5\xea\xab_\xc1\x8bz\xc3\x976m\xfa\xd2&~O\xf1%\xde\xe6j/\xe1r\xcd&|_\x1aS\x88\x8f\xc6\xd2y\x13\xe3<\xe7\x15\x9d-\xe2*L\xcf\x9b\xf8\xab\xdb,\xa9\xb7JQ\x9bz\xbb\xcd\xa4\x9c\xf0\xab\xb7\xa3\xd9\xc2\xc9\xe7\xd1|\x92V|\x8fGVW\x02~\xf6\xcb\x1e\xcdz \xb7\xfd\x0b\xea\x14\xa8\n\xe0H\xa0\xaf\x1f\x9c\x11\x86\xf3\xb3\xa8E\xc9 \xa4\xba\xb2Y\xee\x18n\x91\xa2\xe7H4\xfbr7P?99\xad\x1f\xce\xe6\xdf\xa1|O-\xb5\xb7\x145\xb3\x8a \xb2%\xe34\xb5 \x1a\xc7\xb3\xeaO/4\xf9L_Ps\xe5\x05\x92\x11T\xd4>\xbfLQ\x9b\xc4D(\xfa\x0b\x98\xda\xf4\xf9J8\xf2\xffF\x15\xb5\xcf+)jCb\n\x9bM\x10u\xd82Xc\x118$\xf1t\xb0}\x9c&\xa7@\x80\xabQr\xbc-\xda\xdc\xd6\xa4\xfe\xceU_o6\xc7\xd5\x1f\xcbq7\xf5P1\xea\x8e\xcb\xa4+\xce\xdb\x02\xber\x1fc6\xaaI\n\xeb\\ \xea(*v\x16\xb42\xbc\x814Uc(\x11A\xfc \xcc\xa39\xfa3\xf6\x8c\xe6]\xc7z\xf7\xd8\xfc\xbb\xad\x05\x0f;0'\xa1\x1b=\xe4\xdb\xd1\x01\x1d*,e5\xd56\xaa\xbbV\xd4a,\xccqh\xcc\x12*\xf4\xeb\xb2P@w\xc8\xac\xb0G\xb2\xb8/\xd3O\xd6j\xf7|\x1d\x12\xcc\x10F\x05Im\xc7 #Pz\x19\xeb\x1f;J\xa8w\x03\xca\x8e\x15}\x9e\xa0<\xa0\x91\xfa\x0b\x9f\xc0\x0f\x06z\x0cT\x12\x8e\x00\xfa\x07t\x04\x04\x87\x88~\xa3`\xc2\xc8\xb1GP%;?\x0b\xae5(\xde(\x08u\xa8\x94#\x0b\x94\xc7\xc8v\xd5\x8aI\xc8\xf1\xed#9,?G\x9d\xf9\xa1\xacb4K]\xfdQg\xd4\x9f\x18\x0e]\xd2E[\xe0\x0cph\xca\xaf\xa7\x87\x02\xdbG\x17\x9b\x14\xa1\xe0+`\xa0\xdc\xc4\xc4\x98p\xa0?\xc5@\xe1>!\x0e\x10\x03\xda}\"\x14\x14\n\xcd\xd2\xbd\xb8\xcar=\xd4C\xc0D5\xef 62\xbe\xa6ZY\xea\xe8\x04\xe5\x00\x05\x00?\x13\xe0\xd7\x0b\xb3\xd6i\xf0\xcbA\x8d\xa8\x8b\nT\x13(\xf8E\x0bU\x95Ju\x1a\xb3;\"}\xa9\xd8\x0e\xd5\xba#\x96\xea\x8bL\x88c\xa8\xe4\xca\xe9\xd3\x97\xa3V\xe4\xf2\xe9\xd3W\xfeO\xfb\x9b&\xd9CI\xd4\x99\xfa\xdb\xc7u8*\xe7\x83\x9eQ\xe6\xe7\x07a\xf0Q^*z\x1a(\xa8\x7fL\xad|J\xd3\x8f\x87\x01\xbd^\x8ef\xa9p1\xbf\x0f\xfb\xf5\x840\xc04~\x9c\x02\x90C\x88\xb3Ux\xa8\x07\xce*r\x9aV\x07\xb2*\x8dN9\xcf\x80\x84\xd7\xb3\xaf\x17P\xf0\xfa\x84\xc5\xab\x1bs\xf1\xdcp\xb6\x88\x01\x9c_L\x8c\x89\x7f\x8a\x7f\x8a\xf2\xcd\xe13\xd9Z\"}\x13\x88&\xd3\x01r\xf4O\xbf|l\xf5\xea\xc7~\xa9\xdd\xc8k\xbfC\xbe\x18/Wj><\x11\xcb\xfcS\xc5\x04x\x1b\xd4\x12\xc0\xe5M\xeabS\x93\xaf\x96\x97\x8d\x1a\xfag(]\x11\xbdJ(Z\x12#\x9f\x1e\x86x\x16\xa9\\$\x18O\x0fC6\x0e\xbf8-\xe0f:{\xea\x83S\x8f\xd2\xb3\xe8\x9a\xa8o\x16\xfd4:\x9c\xd3\xcb\xdc)\x17\x8e\xa5\xcb\x10Wb\xbc\"u\xc5iu\xb7h\x8e\x8e~\xbdd\xe3\xca\xe9\xec%\xfb\xaf\x1f\xaf\xd5B\x8f\xb1\xfb\xf3AM\ns\xcd\xe2\xd9WH.gv\xff%\xf9\xe74\xfd\x96\xe3v\xf8+\xb8\x9c\xa7\xf0=\xc2\xbf\n\xf0\xd5S\xeaG\x87\xcf\x8bjWH\x7fW\xc0\xe6\x1d\xe7u>\x85\x96\x7f\x7f[\xffB{[\xe7u\xfb\xc9\xb6s\xd5;la\x9bz\x9bi\xf1\xd5\x08\xddW\xdf\xad\xd4\\z\xbd\xc6\xe5C\xf0\xe4\x83\xdb\xd6|\xa5\x9e\\f\xb7\xab\x9f\xd7\x00te\xbf\xba&\xff\xb9\xdf\x95+B\xfdk\x8d\xab\xe8/t\x90\xbf\n\xcf\x1c\x0bC\x0fM\x90\x84 /@\x12S\xc3>Tm\n\xb1G`v\xfa`?\xfe\x8d\xaa\xa3\xf4\xfe\x01\xd9\x15G\xc6\x12(\xd9,zb\"\x0b\xd5\xe7\xf0e\xb6\xb8\xfcA\xde\xd7A\xdei\xe0\xff\xbb\xb4\x9a7\xd0\xd3\x0e\xe9Q\x81\xc1\xa8R<\xc6\"i\xa0X\xa0\xb6:\xb8I\xdc\x8b(a\x87V\x7f\xbe\xf6\x9c\x1b\xfa\xe3\xa6\xcb\xe7\xa7;4\x07R\x1d\xe9\xf9\x97\xf3]}\x97\xcf\x17\x9c\xec^\xfe\xe1\xab\xcf1\xdcv\xee\xd4\xb5\x8d\xfe\xda\xf9\x977\x9c\xd4\xca=\xd9p\xf9|\xa7[\x19J\xce\xbf\x9ce\xed\xc2\xb5{)\xad\x17e\xdc\xfc\xdd\xfc#\x8c\x83ief0\xf3\x99K\xf0\x14J\xe2q\xb2\"*\xf6F#\xac\x13(\xa9\xb8G\x08jJF\x8dh\x01\x8c\xb8\x87X\xe8#\xd1\x88\xb7\xe2\x05\xb5\x90\xa3\xf1\x1e\xdd\x8dk\x9a\xbe\x97\x085E\xd4R\xa4P\xcd\xce\x8b\x1b\xe3\x86 ^p\x1f\xa0C\xa9eo\xff\xea\xede\x85\x80:\x95\xe7\xaf{6\xc8\xdb\xac\xcd\x1c\xef5\xd4\xcd\x9ds\x91\xc5\xc6\x998\x8bX\xcf\x0bK6\xd7\xf0V[\x90\xe7=\x06\xe7\xd9}V+\x8d\xffh\xcd\xa7\xd7\xc0\xdfJ\x8c\x9bl\xd1\xe2\x8cZZ\x9b5\xc8\xdfW\x91\x89\xb1\x94;\x14\xae\xfeT\xfd\xe9\x86e\xabV-\xdb@\xdaH\x1b\x86\xeaI\xf0\xd9\xeb\xac\x1e\xceD<\x17\xcd\x99[\xc7)\xd6\x90\xcd\xc0\xdf\xcf\xd6l^b\xc3Xe\xf2\xd9NN\xb1\x84\xac\"\x7f\x02K]\xa3@\x8c\x83\xd7b\x8a\xa9\x9a\xcb?.\xe6H\xf7H\ngzXa\xc6\xf0\xd0\xd9\x92A\xee\x13\x88}MO\x05\xa6e\x0e\xfdX\xc2\xfcH\xa7N\x81r\xa0\xd0\xf3\xda\x9fW\x0f\xa8;\xf1h\x10t\xf1\xbbgttO\xf6yu3=\x96\xc2\xfc*\xd7\xa4\xee\xcc\xe5\xd8\xbf\xa0C\x01\xa0\xc2FGsh9J\xee\xcd\xbdZ\xb0\x1b-\x94k\x82\x92]L-\xd5~\x0fh\xceii\xa1.\xea49\xcdQr5\xa6\xf1\xbdI,V\xdd\x93\xff\x85^jf\x0f\x94\xbb_}\xd4,\x93\xed\xacQ6?\xcc5\xe5\xffNV\xe7\x7f\xc1\xcf\xd5\n\xde\x9e\xcb\x8d\xaaY\xd9\x9cN\x9b\xe5%ez\xcb\xdcq\xc6\xa8\xef>\xc1Z\xe8\x0d\xa0\x93Nt\xf1\x8a\xd31\x9a \x00a\x0c\xd5%\x01\xfe\x9e=\xe8 y\xcfh\xde\x99\xab\xab\x0dH\xb8\xc1\x97\xcbJ\x81Z\xf6\x9a?\xfd h\xbdvr\x9ck\xca\xc1@\x1b\x1d\xe5\x1dm\xcdY`\xae^ins\xf0\xeaF\\\x94*\xf6\x08|L\x9cz!/?\xb7)\x14(\x930\x0b\xc9\xe2\n\x15MS4(\x9a\xc8\x97h\x1e\xf0\xd8{\xb2\xba\x99\x92\xe6\xf1-\xee'\xd7h\x8e\xe6\x89\xebo\xea7\xfbcC\x19\xd2\x9e\x19\xca?\x0f\x8b6\xb2\xe2\xf1\x92\xb2'|ub\x18\x88\xd5\xa3@\xb4\xfe\x8d\xcc!\xb3b\xfd\xc3\x99\xa1\xa1\xfc\xbb\xd0f{tz\xf8\x08\x851U\xd2A?=\x8c@\x9c\xe1\xe1 \x05\x19t%\x98\xe4\x95\x89\xc0\xcc\xe5\x00iu\x9a\x93[\x0dN\xf2\xc8i\xe1D\xc2\x0b\xb1\x88G\xddT@\x8a:\xcfp\x15<\xfc(\xf5c\xd3X\xe9\xc9\xc6Um\x02\x8d2\xda\xcf\xb17z\x9b\xdaO\xf2\xedM^\xf6F\xcf\xb4YUfwGs\xfc\xc1\x93#\x91t:\xc2/\x89\xaa\x83\x95\xb6\xce\xe5~\xb1Os\xde]\xb5\xc7F\xd7\xff\xcf\xe7\xdd\x91\xaf\x9e(\xfa\xfc(^\xc8\x17\x8b\xc1\xb1?L\x14\xfb\x8f$\xc0S\x04\xca\xbd\x85\x0cWzT>m\xec'\x7f_\x1a\xa7\x82\x1b\xfad\x8c\xae\xd0\xd4\xe7:\xa5\x0f\xc4\x005\xaeL\x04h\x7f;\x03\xafH7\xdcWgz\xeag\xc4Z\xc6\xc6Zb3\xea{2d5\x90Jj\xa6\xc49\xdec+\xe3\x1c\xf9\x91\\vqz\xe7\xb2Db\xd9\xce\xf4b\xa0\xa9\xc6\xb6\x8fg \xf9\"l\x02@\xd7\xa6\x9dp\xe6QB\xbdb\x00\xfd\xdbS Q\xed>\x11\x80\x05\x93+\x18d \x81p\xb2\x1a\xbe\xee%}\xafL!\x93\x9d\x1c\x99\x17\x13\x83\x87\xf2\xe7\x1e\x0e\x9acd\x1ewH\x03o\x98\xb8\xc6\xe6\x13\xd7p\x19\x80x(T\xec\xbep\xc4\xe8\x08x\xee\xbf\xdf\x13p\x18#\xea\x17\x00:dvQ\x0dq\x9f\x0edA\x1f\xf0QFd\xdcL\xb3\xa6K\xa4m\xd2PR\xcb\xed\x0d\xa4pU?\x03\xf2l\xc3\xeb\xd6\x0d\xaf\xfbzg\xb0-\xaa\x1e\x89\xb6\x85\xd4\x1fjP\xd9\xee\xa9b\xb7\xf9G\xd7aR\xf5\xbf\xfa&\x0f^q\xc5\xe0\xe4>u\xd38\xa4\x95p&\xc3\x1a\xd3\xae\xd1\x84\x0d\xa4`\x0f\xedMGS\x9f\x14\xae\xa1\xae\xf3\x12\x1b\x1e\xd9\x10\xdc\xb5ao\xb0\xf1\xe3\xa1\x13\xdcW\xdc\x9bZ\xb4a\xc3\xa2\xcc\xd9\x9f\xdd\xb0\xb7V5\x9f\x01\xcaR\xbfs2NX \xdbqGB \xa0\xbeO\xa0\x93\xcaK\xd2g\x02\x0c\xe9\xf4\xf0\xc0\xc0BW\xfe\xfd)Sg\\\xf5\xd9\xf9\xea\x9e\xd3\xa1l\xe4\xcb\xf7\xf6]z\xf6\xc0<\xdf\xb2o-_\xfe\xe5-\x0b\xf8\xb1\x9b\xc6A\xa3\x9fKMq\x16\xd3\xad!\x1a\xb4\xc3\xa6Si\xadgy\xf1\xfc\x01\xfd\xbf\xc4\xdb\xb0]K\xfb;S\xea\xc6T'\x90\xe3\xa9\xf3k\x0fPq\xc9\xe6e\xea\xc6e\x9b7c\x0fZT{~*\x1e\x877\x8bb\xea\\H\x85?\xf0j\x19\xd9\xb5l3\x95\x8fP\x1d\x0d\x9c\xef\xd0\xbew\x1c\xefT2\xb2\xf0j\x8aY\x01\x11;\xd6\x00)\xbal\x0dD\xcbueytO\x0fT\xf8\xef\x8f\xdaj\xc3\xb6\xa1\xfc\xf1U\xb6H\xad\xed\xa8\xfa\x1b\x9cX\xf6g\xc9\xac,\xf5\x8fW\xb4\x05\xc9\xcf\xa2^\x14\x8e\xda\xc2u\xb6\xa1![]\xd8v\x94F\xe8\xe7\x14\x94|\n\xe3\xaeQG\xe1\xach`(\xa8# \x83R\xbc'5X\xa9D\xa7\xcc\x07Q\xa0\x18\xcaqM\xcb6g\xfbc'b\xfd\xfau\xb3\x03\x05:'\x97\xf4\xff\x99\xaeH(\x0c\x84\x1b?\xb8y\x19\xd5\xb5\xa5\xfa\xb6\xcb6\xa3~.\xf2e\xa8\xac[n\x16 \xb8\x03\xaa\x8a\xff*\x7f\x80\xb1\x01U\xabyZs\xc3t\xa09\xef\x8b\x9b\xb8R\x7f!G\xd9\xfd\x8d\x8d\xb7\xa9\x8d\xf9\x93MM$\xdax\x8ez\x80\xac$]\xea\xd3{\xd0\xc3\x1dL<\xfc}\xf9\x15\x8d\xe74\xde\xc6\x1a\xe0JZ\x1a\xd5\xf5\xea~\xd2MV\x8c\xd5\x95hy\x16\xd7 >@u\x8d\xbb\xca\xed\x07\x0d\x9a\xe5\x85\xee\x13\x8d+\xb3\xbf\xc6\x03\xe8\xf4\xf5]\xe1\x03\xdf2FqO8j\xfc\x96\xd1\xa5\xb0WC\xff\xbbQq\xed\xcb\x1f\xa4\xebrw\xae\x8b.\xca\xec\x9d\xe4\x84\xab\xbe\xde\xa5\x1a\\\xf5\x9a_\xb4\xfa\xfc\xa7\xe3\xf4\x15\xf6y\x9a\xb6\\\x07\x19O\xbfn\xd4)I\xcdKGR\xa7\xeaH\xc5\x81q\x94\xb8\xdcI\xda\xd1\xc5\x06.\nd+\x10u@\xcf\xb4\x17\x1c\xf5\xd3\x08 \xea\xbek\x96\xd9\xc5\xa4}9\xa5\xeaT\xabv6\x1d\xf6*x\xa4g\xb6e\x057?\x97\x99\xc3\xac\xd4}\xf5S\xa7\x02\xe9\x14\xd5-\xf0\xa0\xed\x13A\x17U\x05\xdb\xfc\x01\x82\xed\x1f\x15\x0bO\x11MlJ\x0d\xd5p\xdb\x11\xed\xd5\xaa\xdd\xa7\xfc\xee\xd5\x05\x9fYw\x96\xd5\xe9h\x9ci6\xfb\\fA\xf6Zc,\xb7rjF\x9cT\x1f\xe5\x82\xd0Mj8kO\xeb\xab51\x8b\xfeT\xbb\xbc\xfdqW\xbd_\xd9n\xe9\xd8`\x17\x957\xae%\xb3K\xab\xe8\xdc\xe9W\xdcs\x96d0\x07\x9a\x82\xe1:\xbb\xd1`\xb4\xb6O\x1dX\x95\xde\x1e\xf9\x03\xd2\x1fs$\xe34\xbc?:\xffSI1\xa2\x00\xa2W-\xbePr}\xea\xc2\xb2\xa3\x8a\x0c\xa7\x1e9\xf5.\xd4\xfb&\xa0P\x9a\x99^f\n\xb3\x148(\xbaW\xa1I\xa2\xc3\x05\xdb`\x1c\xac\xa2`@5a}\x88z\xb5\xeai\xfeV \xbep\x84\x01\xb2P\xd4\xbd+:\x96\xa3\x12d\\j\xc3\"=\xfca\x80j\x15\xa3\x8a\xf0\xad\xe4)W\xa7\xd4$q\xf6{\xc7\xda\xd6\xcd\x9c\xd7p)\x97V\xfc\xf5\xae|\xa37hj\x9d\xac\x8e\x02\xcd\xf6\xe2\x12\x97\xb3\xf5\x0e\xbb\xa5\xc9\xe2$\xb7L\xeb\xe8\x98\xd6\xa1\xca\x0f9\x9b\x1a\\\xf6\xfa\x8e\xda\x81n[ \xb1\xa4k{lG\x8b\x89\xc4.m\x0c\x84m~\xc7T\x97\xc0\xbaE\x8b\x9d\xdb\xf9\xa1\xd1b\x8f\xc8\xad\xb6m\xb9`\n\xbb\x97\x12\x11w\xf2ny\xe6P&\x97\x19:P\xafLJ\xd8\xed\x96Y\x8e\xfa\x7f\xe9\xc0\x8c\xd5_\xeep\x99\x1dNW\xa8\x89\x13\x9e\x9bzV\xdb\xec\x16S\xd7\x83]7\xd6\x0f\xd5E\xdad\x93%i\x0f\xb8\xe7\x99\xac|\xf1\x0c\x03\xbe\x0f\xfa\xe8\xd9\xccE\xd4WM\xc1\x93\x99\x077r\xe2\x0d\xc0\xdeHB\xa8\xb4\xcb6\xfe`UG\xb9Z\x88\xe6\xce\x00\x0d\xf89\xa0N2l2\xdd\xdb\xc9\x85HY\x98\xbd\x1a(\x9a\xc5\x97\x11\xd2\xd4\xd9iw\x18\x9c\xbd\xdd\x93[\xfd\xde`\xaacZ\xa8\x96R;Yz=Tr\xd2vH\x8f\xfe9\x11\xebc.\x0b\xa1\xd6\xb2\xeaG\xe4\x8a\xd2\x13\xba6\xbb*p\xd5\xfc\xce\x85\x1d\x8d\x06\x03'\xbb[\xe2\x8b:\xfa/\x98\xd2\xaaX\xd8\x05\xa5\x9c\xb4CY\xd1\x85M\xf1\x98\xd6\x05t\xcc\xd0-'\xba]\xa3n,{@\xfc\xf0\x0c\x0bc\xf8\x19\x98Ob\xb8\xfe\x15\xe6\xfe\xc2I\x1f\xd1N\x16\x87.\x1f\x94x\x19\x17\xc1N\x81\x0b\xb9F9\xeb\xca\xeb\x9b\x9dN\xff\xadK\xf3\xdf[\xba\xa3\xdeX\xd3r=\xdb\xf4\xe9\x1bW\xcem\xf3\x1b\x0c\x8f\xb0\xdd\x8f\xb0\xc6\xa6\xd8Y+\x02\x8f\xbe\xca?s\xfdJ\xf5\xa2\xc4\xd7g\xccX\xb5u\xcbP\xfd\xb9\xaf%\xc8\x97V^\xbf\xdb\x1b\xe9\xe8\x08[\xad\x7f\xf9\x8b \xb7\xb7\xf4\x84\xd4W\x88\xa0\xaf\x7f;\xe9\xfaW\xe6\x0d\xb3x\x1ev\xb1i\xc8/\x87\xd7\x1eX\x1eS3\xb1\xe5\x07\xc8\xbc\x942\xac\xa4\x04\xf7\x01\xd4\xa9Z\xbe\xc1\xdb\x0cf\x03\xd72\x9d\xd4\xe5/y\xf2\xc9\xcf?\xf1\x04\xed\xbb\xe48\xf0\xaeM@\xd3Q\x0f\xd4\xce*\xcb\x84\xc2\xfd\xc8\xf6\xa1\xa1\xedC\xe4X\xf9\x8dk\x1a\xa2\xf7\xb2?M\x0fz\x17T\x00y?\xb1\xe0\xd5Z\xcb\xc3Yu\xd7\xb3)\xff\xe3\x07\xe9]\xcd\x95\xdf\xf41\x96-\xe3\x97\xfea\x8f\xff7j\xf4\x82~\x94\xcd\xc4\xe1\n.d\xe3\xc4\xe1\n\xbb\x18\x0d\x96\xc4'\xd3\x18\x1c\xb7\xbd\xb8\x9a\x1c\xa7\xba\x93V\xd4\xf8z\xa3tXK\x7f\xfe\xd92k\xcc\xb9d\x17?\xa2\xa7z\x82\x1c\xa7\xfaz\xa5\xb4\xd9\x02K\x8c\x16.\xba>,\xa1\xb8BZ\xa6\xbf`q\x84\x1e\x97'\xbak\x96H\xe8qy\xa2\xfb\xb0\xe6\xa45\x1e\xaf\xbej>a\xc7\xc5\x03\xc5\x05\\C\xd9\x7f\xd5#\xca\xe7H;#p\xc7\xf8\xbd\xd07l\xba4\xbf\x15}\x94\x03\x0b\xd6IR\xb87\x16\x8c\x84\x01\xb0\xde\x8a0\xa7\xfb\x9c\xf0$\xe2\xec=\xab\x06\x06V\xc1\xbf\xfa\xd1\xf6\x91\xed#\xec\x11\xb8\xe4_.\x06\xd1v\xaa\x85s\xf0{g\x1e>\x83\xc1h!\xad\xee\xdaA\xb7b\x0e\xb9\x13/p7\xbc\xd0\xee\x0e\x99=\xdcz\x97\xc1\xa9\xbemi\x94%\x97\xcd\x9f\x9a3)^O\x9aj\xbc<_\xe3U\x8f\xb6NY63dsIr\xa3\x99\xb48E\x97\x10j\xf1\x18\xac\xdf\xfd\xaeU\xf0\xb4\x84*\xcf\x14\x0d33\xcf|v\x0b\xbe\xe3\xe8;\xd4\xdbO\xc6\xe9\x1b\x0eB@\xf1\x9d\xf9,\x97\xfc,\x9f\xd1\\cwd}6k.\x9eu\xd8k\xccF\x1f9\xfe\xb1'\xcc\xe4\x9d2\xd06D]e\xb1\x91x\xdcG\xbeJ\x04\xb3K\x1e.\xd7\xbd}\x86\xf1S\xab\x7f\x86$\x83@\x0ct\x11\x12\"\x9a;2\x00\x1f\xc9\xa9\x00\xea\xb9*\xa4\x8e\x94\x8c\xdb4\xa7\x1e\xdc1_\x83\xe4\x11x\xf57\xb3\xd5Q\xa7bj\xb4X\x88\xa3\xa7\xdf9\x9b\x84\xa7\xda\x02Q\xf5\xbd;\xae#\xcf\x16\x8f{9\x86\xd4e\xbcI\n\x9a-\xec\x7f\xe5\xa5\x90br B<\xde\xd69\xf2dpz\x9c\xdcIV\xaa\xfb\xf3\xffQ:l\x84+\x1b\xebs\xe9i\x0c\xd5#=\x14\x14\xd1\xecT\xac\xf0\xac\x81\x07+R\x98\xd1(\xaa\xe2M\x14\xdeDC$\xe2\n\xb9\xca\x0f\x1da\xe7\xcc\xb1 \xeaO\x1dNg\xc4j1\x11\x07\x9e9\x98\xb6\x9b\xcd\x03\xc4\xdcgqXk\xe8\x19\x84}F\xab\xc5\xe8\xf0\xf9d\xa2\x1e\x15\xa4\xd7\xd6\xd2c\xb6\x8aG\x93,\xb5\xe6\xe5&\x97\xd3.\xd8\xe2\x98\x1a.^\xc9\xb7wwc\x8d\x83>\xc0E\xb4\x12_]3\xfb\x9eU\x15\x88\xb1|\x1e\xe3t{J\x06\xd5f\xaa\xe7\xaa\x82u_\xf9.\x17\xba\\\x81\xff\x1d\xba\xfe*\xea\xf6\xb2W\x95=\xcc\xc5}\xd4lN\xe7\xd5\x14\x8do+\x1d^\xae\xef\xdfV\xcc\xa3\x13\xee\xe9\x91 v\xd8P\xa3>~\x86\x82s\x08\x1a\xa2\xa6T\xb6j\x1dWz~_\xb6\xa4o\x87gS\xd0}-\xad\xfcD\xf1T\x1bd\x82\x0b\xdd-T\x0e\x17\xc0Aa\xc8\xeaYf\xb5\x02\xb2\x05\x98\x1e\xc73,PATcm\xb2\xda\x0d\xd5\xbc4g\xe3\xb8}\x82\x1b\xbd\x95m\xe0E\x1c$B\x8e\x84w\xa2\x9d\xc5\xaa8\xdc>\xab\xac9\x1a\x8f\x96\x18\xe4\x91\xec\xb8JW\xe2\x81\xa9\xb0O\xa5\xf5/9\xffP\xaaJC\xc9XA{,\x99@c,t\x0eE\x05J\xaf\x14\xcbT\xc8j\xbd\xbe9\xec\x00\x958Q\xca\xf1\x95\xd3\xf5\x08&\xa8\x7f \xe4H\x08\x9f\xa0\xfeP\xc1l~K%\x06\xc6\x9e\xf9\x071\x80\xbe\xd1\xbb\xb9\x0d\xfc-\xe8e\xc8D\x0cz\x1d\x13xN\x81\x9b\xbbXuz\x9d\x92\xdd.9\xbd\xe4}\x89M\xc2c\x9d\x0f&\x9c:\xaf\xea\x94Z5\xbf\xe3\xd3\x998\xb7\x13\xf8%\x0b\xd5\xb5\xd5\xbd\xf8\x03m\xb3\x98\xbc\xefom\xf5CB\xf6\x06\x08:\xd0\xe4\xd6\xe1\x87l\xb4\xef\x988\x99\xce\xdf\xc4\xed\xa4~\xf3\xcb\xdc\xa6\xa2E\xb2\x03\xbfj\x95T\xa7\xdf\xc1\xed\xa4YH\x98Y\xe1\xbbv\xf8n\x83V^IN]]\x08\xc2\x8e\xe5CXkg#\xc5s\x0bc\xc0S\xfb\x88B\x92\x1d$\x89\xc3\x9d=\x92\x1f$\x8f\xaak\xf8}cG\xb9&\xf6\xf7/\xa8\xdfz\xe7\xbb\xdf}\xe7\xe4\xbf\xe7\xca\xc6\x07\xb5_\xee\xd1v6\x14<\x81\x127\xb8\x13\xbd\x19\x01\xfd\x13\x18\xb4I\x1aVGG\x02\x99\x9d\x04\xfag*l\xf4\x9f\\RXS\xb2T\x8b\x8b\xae)\xd9\xc2\x9a\x02E\xee\xa4\xca%Y\xa0u\xf4\xf3\xc1~Q~>X\xa4\xb8\x88\x14\xcf\xd0\x85\xb1\x1a\xd6`9\xd3\x1aW\x82\x93k*\x87@_\xd5\x8a\x10pM\xb8\x03]0\xa6*\x83\x81%\xe3a\xc0\x933\x11X\xed\x8c\x81K\xb9M\xfc|\xf4{\x86\xa3F\xd4\x94\xbb\x83\xfa\x91\n\xec\xb7\xbed7[\xd5n\xf2\xa6\xd5l\xff\x92\xcd\xac\xc6D\x91\xfc\xdc\xcc\xcf\xf7@\xa4\xdam\xf5\x98\xc8\xcf\xf18\x8b\x9f\x9b\xb0\x0fe \xafc\xc5\xbc\xf4#\x07\x90gH\x9b\xd0\xc4d\x19d@~.\x8aj\xccl\xc3l\xc9\x9b\x90\x03\xe4eRcx\xeeE\xcc\xe4\x81(( \xcd\xed\x99K\x81\x9e\x99\xcfm\xc2\xbc\x18\xea\xefG\xebX\x94A7\x11\xbe\xd7S\xf5\x15\xb7\xb5\x1c@[\x01l\xda\xd7.%\x19\xc8\xeb\x18\xe6\x05\xd5\xa3n\x01MDs\x07\x88]n\x1d\x80_Q\x1f\xee\xb7\x95 \xda5\xc0i?z\xfb\xd4G\xfcT\xe8G\x023\x19\xb2\xa6T\x9d@e \xe8i\xb4\x81\xd7,\x88\x83\xb0r\x02\xb8\x9d\x1c\nO2<\xb0\xd0\xe8\x95\xe9\x18\xd2l+\xb3\xc0\xb0/\x16,\xc1\x96%\x89\xb9\xadm\xb2\xe0 \xbc\xd3\xdb\x9aX\xd8n\x9b|\x96E\x9a\x9b\xb6\xf7]\x98\x8e\x88\xa2l\x90\xc3\xad\x99\xf4\x9c\x9e\xc6\xcf[m<\x92|#\xb9z\xd7+\x845\x88\xa2 7&\x17\\5S\xf4-\x98{\xfe\xfc\x19\x0eA\x10E\xdf\x15\xd7^\xd9\x1c\x1a\xb8\xec\xact\x93K\xe4\x0c\xc2\xcb\xce\x1a\xad\xdf\xe7\x18\x05M\xf1\xa9^rq]\x82\xeeFm\xdeC%2\xfe\x84vJ\xd2\xf0)W-\xce}O\x17M\"`\xd59l\xb2+\xec=\x85%\"\xab\xe7\xeb\xa3\xf3\xadT\xf2\x98'8\xc2\x01zH3Q\xd2\x90\xdf\xfb\xd1\xa9\xf9Y\xecP~V\xb6\x91\xd8\xb2\xe8Ni\xec\xbc\xcd\xdc\x0b7\x8e\xd5\xf0\xc4\xdb\x9b\xbf \xeb\xce\xfe?w1\xea\xd7\x00x\xdac`d```d\xf2\xcd?\xcc\x12\x1f\xcfo\xf3\x95A\x9ee\x03P\x84\xe1BY\xf1t\x18\xfd?\xf0\xff\x1c\xd6;\xac\"@.\x07\x03\x13H\x14\x00c\x04\x0c\xe8x\xdac`d``\x15\xf9\xdf\n&\x03\xff]a\xbd\xc3\x00\x14A\x01\x8b\x01\x8a\x8f\x06_x\xda}S\xbdJ\x03A\x10\x9e\xd5S<\x91`\x11\x8c\xda\xd9\x18\x8b\xab\x04\x0b\x11\x04\x8b\x80\xda\xf9\x00\x16\xc2b)6\x16\xe2\x0b\x88\x8d>@D\xc8\x13\xc4\"\xe8\x03X\\o\x93\xa0\x0f!\x87\xad\x8e\xdf\xec\xce\xb9{\xc7\xe9,_\xbe\xd9o\xe7gg\x93\x98g\xda \x98\xb9#J\x86\x0eVYp>uC4\xd3&*\xd9<\x02=$\x8c\x15\x03\xec\x13\xf0\xbeg9\xd3\x1aW@.0\x9f\xa2q\x11\xea\xf2\x87\xfa- \xf5\xf1\xfc\xea\xf1\xdb;\xc6:p\x06t\"H\x8fU\xe5\x05e\xe8\xdc\x0f\xbe\x035\xe4\xd5\xe7\xfc\x0bVg(\xf7[A\xe3\x11x\xad9\xcf\xdd!\xd6\xde\xb4\xf7EM\x9f\x8f\xea\xdf\x97\xef\x154\xfeN\x86&\xd3\x9e\xd7\xf0wj\xb3t\xfe\x99\xb3\xd4\x9e\x14e\xcf\x83\xe8Lp\x8c>\xef\x8a\x87\x86w\x91\xef\x86\xf5>G\xe0\xd9pfz`\x13\xcd|\x08\xb4\x1b\xde\xe2\x04\xfc\x05^\xaaa\xd9\xc5\xbc\xf8>\xe4\x8c\xc7\xf0\xb6)\xc7o\xa9\x0bo\xa5\xb2\x82M\xdcg+R\x12\x8am\x1a\xb9Rq\xd1\xed,\xf7\xab\x8bRJ\xb9\xe0\x021\x97\xd4\xd5X\x89\x1bT\xaa\xe4N7t\x8b{I\x96E\x97\\\xeeF\x16\xff\x18\xeb8\xe3\x11U\x0d\xba\xc9\xcc\x1emb\xcd\xf9:f\x97N\xb1&\x92\xfd\x03j9\xccY\x00x\xdac``\xd0\x82\xc2M\x0c/\x18^0\xfa\xe1\x81K\x98\xd8\x98\x94\x98\xea\x98\xda\x98\xd60=avc\xcec\xeea>\xc2\xc2\xc1b\xc4\x92\xc4\xb2\x88\xe5\x0ek\x0c\xeb.\xb6\"\xb6/\xec\n\xecI\xec\xa78\xe48\x928\xf6q\x9aq\xb6pn\xe3\xbc\xc7\xa5\xc1\xe5\xc35\x85\xeb\x11\xb7\x01w\x17\xf7)\x1e\x0e\x9e\x08^-\xde8\xde\x0d|||\x19|[\xf85\xf8\x97\xf1?\x13\x10\x12\x08\x11\x98 \xb0JPK\xb0Lp\x9b\x10\x97\x90\x85P\x8d\xd0\x01a)\xe1\x12\xe1\x0b\"Z\"WDmDW\x88\x9e\x11c\x113\x13K\x10\xdb \xf6O\xcf~\x95\xfd/\x07\x0f\x87\x06\x87c\x8eL\x8euN\x12N+\x9c\xde9K8;9\x979/p>\xe5\"\xe0\x92\xe0\xb2\xce\xe5\x9bk\x94\xeb676\xb7\x12\xb7-n\xdf\xdc\xcd\xdc\xcb\xdc\xb7\xb9\x7f\xf3\x10\xf30\xf2\xf0\xf3\xc8\xf2h\xf38\xe3)\xe4i\xe1\x19\xe7\xd9\xe2\xb9\xca\x8b\xc9K\xcf+\x08\x00\x9fs\xaa9\x00\x00\x01\x00\x00\x01\x17\x00\xa7\x00\x11\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x01\x00\x00\x00@\x00.\x00\x00\x00\x00x\xda\xad\x92\xbdN\x02A\x10\xc7\xffw\xa0\x91h\x0c\x91\x84\xc2\xea\n\x0b\x1b/\x87\"\x82T\xc6D\xf1#J$\x8a\x96r\xf2qr|\xe8!'\x89O\xe13\xd8\xd8X\xf8\x08\x16F\x1f\xc1\xde\xa7\xb00\xfewY\x81 \x851\xdefg\x7f;73;3\xbb\x00\xc2x\x86\x06\xf1E0C\x19\x80\x16\x0cq=\xe7\xae\xcb\x1a\xe6q\xa3X\xc74\xee\x14\x07\xb0\x8bG\xc5A$\xf1\xa9x\x0c\xd7ZB\xf18\x12\xda\x83\xe2 D\xb5w\xc5!\xf2\x87\xe2I\xcc\xe9a\xc5S\xe4\xb8\xe2\x08\xf9X\xf1\x0b\xa2\xfaw\x0e\xaf\xb0\xf4\xdb.\xbf\x050\xab?\xf9\xbeo\x96\xddN\xb3\xe2\xd8\x8d\xbag\xda\x8d\x1a\xd6\xd1@\x13\x1d\\\xc2A\x19\x15\xb4`\xe0\x9es\x11\x16b\x88\x93\n\xfck`\x1b\xa7\xa8s\xdd\xa1}\x9b,\xec\xab0\xa9Y\x83\xcba\x0cD\xf0\xe4\xae\xc8\xb5\xc8\xb5MyF\xcbMv\xe1\x04Yd\xb0\xc5S\xf7\xb1\x87\x1c\xed2\x8c\xe5\xa2\xc4\xe90~\x99>\x07\xb4/\xe3\x8a\x1aqJ\x8c\x9e\x16G\ni\x1c\xf2\xf4<\xfd\xd2#c\xfd\x8c\xb40\x14\xeb\xb7\x19\x18C~G\xb2\x0e\x8f\xff\x1b\xb2\x07\x839ee\x0cKv\xab\xaf\xad\xd0\xb2\x05[\xda\xb7{\x1e&V(\xd3\xa81j\x951\x85M\x89Zqr\x81\x1d7\xb1,g\x12K\xdc\xa5\xfeX\xe5\xe8\x9b\x1a\xad\xf5\xe50\xe9\xed\xf2\x96\x9b\xcc\xdbQY{\xd4\n\xaa\xfd\x9bM\x9eY\x16\x98\xb9\xd0\xb6z=\xc9\xcb\xd7a\xb0:[jE\xdd\xa2\x9f \xac\xb2\x0bBZ\xecZ\xff=n\xf4\xfcs\xb8`\xcd\x0e+\x11o\xcd\xfd\x02\xd4\xcc\x8f\x8f\x00\x00x\xdam\xd5U\x94Sg\x18F\xe1\xec\x83\x17\xa7B\xdd]\xf3\xfd\xc99I\xea\x03$uw\xf7\x02-\x05J;m\xa9\xbb\xbbPwwwwwwww\x17\x98l\xee\x9a\xb5\xb2\xde\x95\x8b\xb3\xf3]<3)e\xa5\xae\xd7\xbf7\x97R\xe9\x7f^\x0c\x9d\xfc\xce\xe8V\xeaV\xea_\x1a@\xf7\xd2$z\xd0\x93^\xf4\xa6\x0f\xd3\xd0\x97~\xf4g\x00\x03\x19\xc4`\x860m\xe9[\xa6czf`(32\x1333\x0b\xb32\x1b\xb33\x07s2\x17s3\x0f\xf32\x1f\xf3\xb3\x00\x0b\xb2\x10\x0b\xb3\x08\x8b\xb2\x18\x8b\xb3\x04e\x82D\x85*9\x055\xea4X\x92\xa5X\x9aeX\x96\xe5X\x9e\x0e\x861\x9c\x114i\xb1\x02+\xb2\x12+\xb3\n\xab\xb2\x1a\xab\xb3\x06k\xb2\x16k\xb3\x0e\xeb\xb2\x1e\xeb\xb3\x01\x1b\xb2\x11\x1b\xb3 \x9b\xb2\x19\x9b\xb3\x05[\xb2\x15[\xb3\x0d\xdb\xb2\x1d\xdb3\x92Q\x8cf\x07vd\x0c;1\x96q\x8cgg&\xb0\x0b\xbb\xd2\xc9n\xec\xce\x1eLdO\xf6bo\xf6a_\xf6c\x7f\x0e\xe0@\x0e\xe2`\x0e\xe1P\x0e\xe3p\x8e\xe0H\x8e\xe2h\x8e\xe1X\x8e\xe3xN\xe0DN\xe2dNa\x12\xa7r\x1a\xa7s\x06gr\x16gs\x0e\xe7r\x1e\xe7s\x01\x17r\x11\x17s \x97r\x19\x97s\x05Wr\x15Ws\x0d\xd7r\x1d\xd7s\x037r\x137s\x0b\xb7r\x1b\xb7s\x07wr\x17ws\x0f\xf7r\x1f\xf7\xf3\x00\x0f\xf2\x10\x0f\xf3\x08\x8f\xf2\x18\x8f\xf3\x04O\xf2\x14O\xf3\x0c\xcf\xf2\x1c\xcf\xf3\x02/\xf2\x12/\xf3\n\xaf\xf2\x1a\xaf\xf3\x06o\xf2\x16o\xf3\x0e\xef\xf2\x1e\xef\xf3\x01\x1f\xf2\x11\x1f\xf3 \x9f\xf2\x19\x9f\xf3\x05_\xf2\x15_\xf3\x0d\xdf\xf2\x1d\xdf\xf3\x03?\xf2\x13?\xf3\x0b\xbf\xf2\x1b\xbf\xf3\x07\x7f\xf2\x17\x7f\xf3\x0f\xfff\xa5\x8c,\xcb\xbae\xdd\xb3\x1eY\xcf\xacW\xd6;\xeb\x93M\x93\xf5\xcd\xfae\xfd\xb3\x01\xd9\xc0lP68\x1b\xd2s\xe4\x98\x89\xe3GE{R\xaf\xce\xb1\xa3\xcb\xe5\x8e\xf2\x94M\xe5\xf2\xd4\x0d7\xb9\x15\xb7\xea\xe6n\xe1\xd6\xdc\xba\xdbp;\xda\x9bZ\xed\xcd[\xdd\x9b\x9d\x13\xc6\xb5?\x0c\x1b\xd1\xb5\x95\x18\xd6\xb5ykx\xd7\x16~y\xd1j?\\3V+wE\x9a\x1e\xd7\xf4\xb8\xa6\xc75=\xaa\xe9QM\x8fjzT\xd3\xa3\x9a\xe5(\xbbv\xc2N\xd8\x89\xaak/\xec\x85\xbd\xb0\x17\xf6\x92\xbdd/\xd9K\xf6\x92\xbdd/\xd9K\xf6\x92\xbdd\xafb\xafb\xafb\xafb\xafb\xafb\xafb\xafb\xafb\xafb\xafj\xafj\xafj\xafj\xafj\xafj\xafj\xafj\xafj\xafj/\xb7\x97\xdb\xcb\xed\xe5\xf6r{\xb9\xbd\xdc^n/\xb7\x97\xdb+\xec\x15v\n;\x85\x9d\xc2Na\xa7\xb0S\xd8)\xec\xd4\xec\xd4\xbc\xabf\xaff\xaff\xaff\xaff\xaff\xaff\xaff\xafn\xafn\xafn\xafn\xafn\xafn\xafn\xafn\xafn\xafn\xafa\xafa\xafa\xafa\xafa\xafa\xafa\xaf\xd1\xee\x85\xeeC\xf7\xa1\xfbh\xffQN\xde\xdc-\xdc\xa9\xcf\xd5\xdd\xf6\x1d\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x0f\xfd\x87\xfeC\xff\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x0f\xfd\x87\xfeC\xff\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x0f\xfd\x87\xfeC\xff\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x0f\xfd\x87\xfeC\xff\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x0f\xdd\x87\xeeC\xf7\xa1\xfb\xd0}\xe8>t\x1f\xba\x0f\xdd\x87\xeeC\xf7\xa1\xfb\xd0}\x14\xf6\xf4\x1f\xfa\x0f\xfd\x87\xfeC\xff\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x0f\xfd\x87\xfeC\xff\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x0f\xfd\x87\xfeC\xff\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x0f\xfd\x87\xfeC\xff\xa1\xff\xd0\x7f\xe8?\xf4\x1f\xfa\x8f\xa9\xee\x1bv\x1a\xedNj\xffHM\xdep\x93[q\xabn\xee\x16\xae\xcf\xeb?\xe9?\xe9?\xe9?\xe9?\xe9?\xe9?\xe9>\xe9>\xe9=\xe9<\xe9<\xe9<\xe9<\xe9<\xe9:\xe9:\xe9:\xe9:\xe9:\xe9:\xe9:U\xa6>\xef\xf7\xeb:\xe9:\xe9:\xe9:\xe9:\xe9:\xe9:\xe9:\xf9\x7f=\xe9;\xe9;\xe9;\xe9;\xe9;\xe9;\xe9;\xe9;\xe9;\xe9;\xe9;\xe9;\xb5}\xb7\xea\xadV\xcf\xceh\xe5\x11S\xa6\xe8\xe8\xf8\x0f\xb7\xaa\xd9o\x00\x00\x00\x00\x01TP\xc3\x17\x00\x00PK\x07\x08\xea\x14{\xf5\x80[\x00\x00\x80[\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00fonts/glyphicons-halflings-regular.woff2wOF2\x00\x01\x00\x00\x00\x00Fl\x00\x0f\x00\x00\x00\x00\xb1\\\x00\x00F \x00\x01\x02M\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?FFTM\x1c\x1a \x06`\x00\x8cr\x08\x04\x11\x08\n\x82\xa9$\x81\xe5e\x016\x02$\x03\x86t\x0b\x840\x00\x04 \x05\x87\"\x07\x95Q?webf\x06\x1be\x8c5\xec\x98\x8f\x80\xf3@\xa0\xc2?\xfe\xbe\x08\n\xda\xf6\x88 \x1b\xact\xf6\xff\x9f\x94\xa0\x86\x8c\xc1\x93\xc7\xd8\xdc,3+\x0f2q\x0d\xcbF\x16\xaeYO\x1b\xec\x04&>\xb1\xe9\xb1b\xd2m\xa45\x81Z\x8e\xe6H$\xb1\xaaY\x8a\x19\x9c\xbd{\xecH jd\x86\x0b\xd5\x89\x0c\xfc\xb2%\xf7\xb9\xd9\xa7\x7fy\"\xa7\x04\x03\xf7\xf6\xd7+\x8d@\xb9\x8c]\xbd\xabe\x9f\xfb{\xfa\xd2\xfbv\x90\xa0Nc\x8b)\x0e\xbbn\xf9\x93\xc9?~?\xe8\x90\xa4h\xf2\x00\xff\x9e_\xe7&i\x1f\xc6\xca\xc8\x1d\xd1\x9d\x05\xc1\xa4\x8b?\xba>\xfc\xe5^K \xfbv\xb4-\x1bc\xdb\x8d1\xed\xf4\x80\x12\x892K\xa0\xe1y\xb7\xf5,'n\xe4\xab\xe0\x00\x07(\xf03Ewi\xe0B\x05\x17\x82\xa0&\xa9\xff\x0b\xe9\xceT\xb4lh\xd80M\x1a\xd2\xd8\xda\xd2\x86d\xe5Y\xd8r\xf1\xef\xb2\xac\xb3nti\xde]\xddyur\x95\xb4\xbc\xae\xfb\x99\xee\x13VXsj\x0e\xa1\xa2\x9e\xe5gMn\x19\xaa\xd3\x99H\x81W\x95\xa9\xc3\xd4\x08 r2\xf4>iT`V7\xb8\xcdR(\xb1\xa8\xc9\xcf\x1a\xe0\xff+\xa0o6\xf3'c\xc5\xc8B\xb0\x8f\xe6\x06\xeb4\xe7\xb7\xd6\xce\xb9\xdd\x7f\x87\x83\x8b\xe3\xbf\x9a\xaeT ]a[Qd<3wq8,\x8e\x85\xeerTI\x16\xa18\xe1\x12\x1c\x8e0>E\xb8?\xf9*E\xa8\xe7\x97\xa6\x95#\xcf\xfa7'\x8d\xec\xdd\xfd\x86S \x0c\x0boc\xfb\xca\xb7\xed_\x8b7&#*\xd1+)\xbd\xb3\xa0\xd0+4a\x01\xb0A6\xb6c\x8c\xe7y\xb1\xd9\xa3\x86f(b\x19F\xe9\xe6\xe4\xff\xe9\xb4$;{ YA\xc31vP-tG\xf8\xff\x8c\xe1\xc0\xb1\x15\xcd\"\xfb\xb0\x95\xdb\x01C\xc2f- W\x82\xf7\xae\x02\x9a\xd4\x99\xceuK\xd6\xb0K\x08\xe3#\xad\xed\x0e\xe4\xac\xd6*K\x86<\xdb\xfc\x04 (\xd1\xdf\xeb\xd4\xf7\xd7\xffZ\xfe`\xd9\xab\x0c\xe5\xb5[\x97%\xeaY\x05T\x8a\xac{%\xaf\xc9\x8a$\x88\xad\x10\xa0s{o\xef\xed\x19\x9c\x17\xf2\x88\x83\x18\xd5\xbb\xefvt\"p\xe0\x9c4`\xc8\xea\xdf\xa9\x8a\xcf\xa4}o\x0c`\xe3\xb3\xdd\x14\xfa'n\x14e\xdc>\n\xe4G\x1e5s\x00z\xf3_N\xf3\n\x92PK\xd3\xa6vmU\xde\x0b\xc9\xbe{z\xbd\xdc\xf2\xee\xf3\xff\x9f\x19\xf8\x7f\xf8\x8c\x87\"3`l\x0d\x92\x1c\x03\x96W#\xd4\x90\xbd^\x18@+\x8d,\x07c\xb9\xc9ko\xa9\x8dAO\x1bp\x15nu\xb5\xa7\xd4z\xf3\x96zJ)\xf5\xdc\xce\xa5\x1e\xf7\x98\xdb1\xc7}\xe1\xe1\xffO=\xde\x7f\xad\xb6\x80x\xbeR\xc6\xc4`\xc1J\x89`\xa7q\x83\x15\xa5\x82Us/\xbf+\xf8k\xd2v\xc71xl\x1a\xdd\xdf\xe7j\x12l\x05\x96El\xec\\nD\x8c\xc8\xc3\xc6\xb6\xafV\x86\xb1\xe6\xff\xd0jg\x9b{Zd\xe5\x89\x08z7\x8f\x0b\x145\xff\xdf!\x04xm\xc25o\xc2[\x07\x1c\xbd\xbfu\xef\xfb&\xb7\xaf1\xda\x82H\x10BkA\xe2\xec\x08qr\xea\xceR\x90\xc4\x0d\xa3\xb7\xb0\x16\x8f(\\gh\xf4\x10\x14\xc87\x89\xec\xd2\x8ay\x8f=\x86H\xb5Z\xf3UPh\xe9\xd0$8\x10Rg\xd3\x05\xc4\x18\x80z\xc2g\xcd\xad\xc9N:\x8b\xe0\x001u\xac$\xdc\x85\xaf\xa4\xa1\x9e>R\xfd]\xe5\xfa\x14\x97\x0e\xa6\xac\"\x9f\xf4f7\xbc\x97\x0b\xf5K\xaf^\x7f'\x98\xaa\xeb\xbd3\x93+E/\xbc\xc4^\x89YU5]\xa8NB\x17.\xde\xca\x8b\xa5\xd28\xdf\xc5+\xce\xcd\x8f8\x8f\xf9,|\x89{M|\x8cA\x8a\x11\xe5ua|\xd0a\x88\x92\x7f\xec\x8e\xd5\xde\xcb\x85\xd5\x9d%\x00\n\x7flKG\xa2P\xed,\x17Nu\x14\xe6\xdc\xd4k\xfec\xef8mX@\xda\xd3d\xff\x17\xcc\x98?\x7f\xf1\xfc\xda\xf3\xa2\xe7Y\xd3&\xcf\xfe{\xea\xf6\x94\xf8\xb3\xc7\xcf\x0e?\xdbP\xdc(\xae\x14G\x8a]\xb6\xbf\xcf\xc6\xe4\xaf\xe4O\xe4\x8f\xe4\xb7\xe4\xd7\xe4\x97\xe4\x06r-\xb9\x92\\LF\xc9\x089\x97,&\xa7\x93y\xe48r\xac\xfb\xb4\xfb3\xf7\x1f\xdc\x9f\xb8?p\xbf\xef>\xea~\xdb\xfd\xba\xfb\x15s\xe8\xe4\xff\x05\x8b\x9e\x12\xd0\x10\xa2\xd3D\xc7\x08\xa4z\xf31\xfa\xa1?\x12\\U5\x16q=\xad\xd9t\xd1z\xd4\x92\x0e\x86&Z\x90nj\xa2%\xe9mM\xb4\"}\xbc\x89\xd6tk\xdeD\x1b\xbawh\xa2-=\xffm\xa2\x1d\xbdB\x13\xed\xe9\xf576\xf1\xf4\xae\x83&:\xd2\xbb\xc9qt\"\x0b\xd61:\x93\x15\xac\xeb\xd0\x95\xac\xa9u;\xf4\"K_\xa1/Jd\xd6c0\x96l\xb2\xf5\x1c0\x1d\xb2\xc5'^\x03\x16B\xb6\xf98VC\xb6\xd5zg\xb0\x06\xb2\xbd\xac\x0f\x06[ ;\xca\xfad\xec\n\xd9Y\xd6\x17b\x7f\xc8\x83u\x1d\x0e\x87\xbc\xa9u;\x9c@\x9e*}\x01\x06y\x89|\x0c.\xa9\xac'C>\x13\\g=\x1b\xf29\xe0V\xeb\xc5\x90\xaf\x01\xb7[o\x86|g\xf0\xa0\xf5^\x90\x1f\x0c\x9e\xb6>\x8a\xfcd\xbc\n9\xad\xcf\xc7\xfb\xe4\x17\xee\xd8\xc5\xf8\x94\n*E|A\xa5\x0e\x8f\xe3\x1b*M\xad[\xe3[*mO\xdc\x0e\xdfQ\xe9z\x1c?P\xe9n\xdd\x1b?R)Y\x8f\xc1oT&[\xcf\x01U*\x8b\x955\x10\xc0S\xd9\x0cMB\x0b\xfe\xec\x04\xa1\xa5\xf0[\xb3\x13\n\xad\x84\xdfoYDh\xad\x18\xd5{\xec\xd1,}1f\x12?\x9b\x00\xab\x93N\x8fN\x9c\xa2 ]\xd4O/^;\\\xda\x0e\xc2J\xca\x0d\xcfB\x06\xc7EsJr\x19\x04\xaa\x90\x19\x01\xa0\xc4\x9a\xf5\xc6\x0f\x14'\xf2\x85g\x12/\xe3\xe3\xd1B\x17%\x9f\xa1\x1eo \x1fC\xf5\xea\xban\x957\x8b\xdc:\x05|\xf5y\x83Kt\xb2&\xf7$\xa7\xd8s\xaf|\xb9\xf5wP\x88\xf9\xc4\\i]\xbe$Z\x12@+\x01\xcd\x0c\xb6\xb6\xd5\x8090x]\xbbr\xb8\xad%\xbe\xc8\xd5+\xf6\x07RU\xacEm\x87+\x16\xdc\xb0\xaa\xa3;w\xa0u\xac\xc09/I\xbc\x05\xd47\xc87\xd5\xa6\xb9Q\xfelu\\\xa6y\xd0\x0eW\x8b\x10N)\xeb8\x89\xdc\xb0vY\xee*u\xb4m\x02\x94\xa1\xb1\xbf\xe9\xe2\xa9\xe2\x04\xbam( f\x06\xcaE\xbd\xf2\xffG8\xb2\x0c\xa2j#I\xac\xbdR\x8e\xcc\x17\xf9z\x0c#q\xb8\xdf\xb7\xdf\x01\x06 \x84)Y\xa0\xd7$\x8b\x0b\xe1\xd0\x9b\x86c_%\xbfm-{!0-`\x0b;\xe1\xe5\x85\xac\xf1\x14hyV\xf5\xe4\xc1]Hv! \xcf\x1ft\x1ca\xbd\\K\xef\xc5\x10\x1e\x06\xa5[\xcc1{\x1a\x03\"\xe7j 6@\xec\x963T0%\xa5\x13\xbf\x0f\xe9\xce\x98\"\xc7\xd4\x99\xc6ZI\x86G\xe4\x06\x9bS\x93\xf7\x8d\x82.\xb3\x11\xc4\xce\xa3p\x07\x81\xc6\xd3\xacS\xc61e\xe9\xfb\xd9\x93\xc4\xd8\x9b\x9d\xf9\x0cY\xc1\x1e\xffv\xbb8\x1a\x08d\xb1\\\xb1B\xa1\x17l\xa1S\xfb\xfeR)\x06\xd2\x13\xd3\x86\xe7\xf9\xaf\x96\xae\x80\x0b{\x02I\x8a\xd3\x86\xf4\xd2%\x9d\x94\xaf>\xfb0\xd0\x8e\xda\xa6\xb3\\\xf0'\x94cg\xbd2%4\xa0Q\x8eD\xa1\n0\xcd\x923B\xb2\"\xc9M\x8e\xd5\x8e&\x80\xdb\x8ahI\x15\xc7\xc2\xda\xa7\xd2Rg\x10\xb7ME\xa4\xa1\xa9\xa1\xb6\x9a\x0dI\xbd\xce(\x07\xa9\xde\xd55U\x96D]\x0c}\xf2\x1d\x99\x07b\xed8$\x97\x87\xec8\xa8>\xf3\xe1X \x01\xb2\x07h\x95\"l\x1e\xb5\xce\x80\xe2j\x1c\x9d.%\x88\xdb\x80\x18HH\xc7-\x0bI\x9a\xa6\xdd\xb8#1\x92\x1dC\x014\xf5\xdeY\xde\x017\x84\xed\xee\xae\x12\xedY\xdd\x96\xa1V\x0co\x08\x1a>P\xca]\xa16\xbf\xb7\x07\x98\xf6\x99O4\xff7f\x1a\x0d\xbd~\x00\x18\x1eAJdYF\xd5\xc2\x80\xca.\x96\xdeo\xf5\xc3\xfey) \xc68l\xc6\x0b\xb622\x8ee\x8a\x9c\x1f\xa6\xd21H\x1b\xa1[\x01t\x89\xb0@!\xc8\x85\x0c2\\\x80@\xb8\x085\x06\xc4\xd9\x93\xca%Z\xd7\xee\xfc\xdbk\xde\x92\x08\x06a\xf5\x9d\xae\xdc@\xfa.`n\xa83\xcaOF\x8c\xa2\x10R(\xf3\x85\xa5\xb6\xf7\xff\xbdZ\x01kLk\x05F \xedHWjY\x1f\x0dI\xa4\xea5\xd7\xe7*\x13\xf16\xda\xcee\xb5Sbk.\xa4\xbc5F,\x17\xec.\x95\x02N0\xdf\xd4\x99\x92\xb9\x80|\x94\x86V\xa6\x80||~\x05N\xf4\x87( 4\xb7\x9d\xec\xda],\xec\x1aJp|~\xf9xe\xd3\xc9A\xa8\xd4\x1c\xa1\xaf5\x88\x88/\xbb\xda\xbbS\xa4\xfd\x04\xe4\xf4\x94\xd0v\xf2\xd7\xdcy?\x9b\xf9\xb2'_v|r\xea\x84\xcbX\xdc\x06\xf8\xeeH\xe9Q\xca\x05\xb0\xb5\x15\x05\xc4\x93B@=\x0b\xddX\xac\xdf\xfa\xacB\x13\x189\xcb4\xb3\x98\xab\xc3T\xa9\xd8B\x89B\xa9c\xa0\xad\xc1\x18\xabH\x91P\xa3\xce+\x82\xf2\x89\x81_\x93\x93\xd5YH\xd9#\xac$\xaa\xcb\xca`\xa0\xecF\xf8\xa3\xf1B;\xe3\xb5\xc2+\xdb\x11\x94\x85BPR\xb04\xcc\xbc t\x04\xad:t\x08\xf5\"Z\x13E\xbaJ^!X\xc2\xc7\x93\xe0\xacq4_dTW(5\xe4\xdc\x80\x04\xa7\xe5\xff\xe4\x1f\xb8\xdaI\xb1\x94U\xc5\x87\xd2A\xcdz\xfe@U6\xffn.WGX\xfd\xc0\xc1\x05\xe8H\xecRK\xc0\x16\xdb\x1a&\x08'swM\xb1j\x8a\xca\x8e\x98\x8b\xb1<\x9f\x94\xb1\x983\xa6)\x80\x96\x9d`#F@\x12\x0c\x18\x0cF \xd4\xa2\xe0\x08\xfe\xd8v\x8do\xcdb$x\x0c\x07\xef+\xb2\xe0\xbcu\xfb&\xb4}\x89|\xcaX\x18&[\xd9\xaa\x908F\x8b-\xb9E&/>\x8a/\x17\xd1G\xc5.a\xeaz^\x8a\xde/\x83\xd4\xfe})\x9c\x11\xb2\x13\x92\xf3'\x93x\xa9\x91$O=<\x01\xc7\xc2z\x99\xa4o\xe4\xa7\xe1A9M\x1f\xd8\x9d&\x1d\xf2~\xee\xa1\x99\xb93\x19r\xb5\x053g\x9f\x9c\xa6'\xbf8\xd2\xa3\\\xb0-\xb6MDz\xc8\xe8\x11\x98\xf8k\xba\xcd5\x86\xf9\xb1\xb4A\n\xdd\xc2\xfd\xaaG9\xa9\xe4|1-\xd8! \xc787\xfb\x10[\x9c\x7f\xf4\xa4,mR\xeeu|\xa657\xae\n\x1c=X\xfe\x91\xa4,\x98aJ\xa7\xd9\x1b\x16\x9b\xb8^t\xb4N\x9b4\xd3\xd8\\f\x10\xd0\x84]Az\x1bH^\x027\xb7\xaaF\x95\xe8\x1c\xfe\x95\x99\x84&k\"\x1bLU>}\xec>\xe7rB\xe5X(\xdb\x82\xaa\xeb\x82\x02T\x9a%\xbf\xab\x0bJ\xaa\x08\xbf\x84\xaddhK\xc4\x1f\x94\xf3\xb6P\x93\xb2K\xc1\x1eTFaA\x873HH\x86C[r;a\x9b\xc0\xb6d\x02\xb7\x99\x17\x87\x1a\x9554\xc8\xcc\x0c\x89\x97lL\x84k\x03jG\x0f\x1a{\xa1\xec8\x9fh~\xe4\x8f\x07\x0dfR@\x03\xd0\xec\xfc\x1e9w\xe0B\xa8\xa4\xe0\xd00\xeb\x0bzS\xf5\xf4\xb0\xe2\xff'\x97\xa0\x14\x02a7\x03\x82@\xdd@N\x9b\xb1\x8a\xdd\xc6\xb9l\x91b\x18j3\x0fhN\x04\x13\xee\xb2X\xf6\x8bF/\xc9\xede\xa2s\xa3\xd9'\xfa\x8aDsQ\xab\xf1<\xfek^\xd3\xed\x1d\xf2\xd7\xbc\xb2\xfd\x88ZASO\xa8i\x17d\xbaSJ\xe3x\x1cN4D\xbd\xb3\xc0K\xd3!\xb4\xb9\xd4\xf9 !\xd9\xabv\x89\xachA`\xdbE\x96\xb7X\x10\x90\x95\x00\x02\xbc\xca-\x0d\xa2P\x0d\xed\xc4:\x9f\x82\xdb\xd1\xa4\x1b\x7fC\xea:\xc2\xc2W\xcdzS\xbds\xc4dO\x0c:\x08\x10\xb6_\xbf\xab\xd4\xcb`\x8a:t\xc1a\xce\xb7\xd0\x91\x0b\x1e\xa5\x86\xb2\xcd\xd8\xb3\xfa\xa2\x16\x81\xae\x0d\xbcIY\xf0\x044\xc7\x0c# \x10\x90\xf8*\xd2\x1c\xcd+<\x03\xeaq\x00n\xb0o\xd4\x00\xb8u\nU\x08\x04\xcccww\x8f\xf3x$d\xb5\xb3\xf0\x1b\xc6\xbf\x0e\x9d}\xcf\x81\xfb\xd6\xc194\xcc\xfd\x9a\xed\xfc\x039p\xac*T:\xfa%G\x15Q\xe6\x85^a\x9f\x8b\x15\x87\x10\xe4\x03\xdd\xcb'\xa8\xe7e\x83\x1e\xf4b\xf6\xa8\x04\x14\x14\x8al-\xd5\xdc*X\xddL\xe7%*\xc5\xba\x08\x19\xb8.\x85\xda\x8a\xc8\\\x8a@pR$T\xe5*K\xd6\x18\xcd\x05\xbd\x08\xb8hp\x87\xc0\x88\xc8\xe8\xc1\x82\xdf\xe3\xa6m\xfa\xc1\x1b\x91\xe2-/\x93oS\xda3\x8e\xdf\xc2E\x8d\xe0\xcf\xceto\x7f\xb8\x07\x9e}\xe7\xd0\xb6V\x87o\xf5\x07eJ\x0b`<\x99$\xf6\xd9t\xed\xd8\x12\xbd\xdf\xfc\x1f \xaa]g*\xdfZ\x9b\x0f\x84\xb56q\xb0\xc0\xf9l\x92\x04\xf8~\x1b\xf7E\xaf\xab\n\x86S\xfa\xb8/\x8a\x92\xf9i\xa3\xc4T\xc6t\xcdk\x82\xc7\xae\xe0\xb2W\xdd\xc3\xbe\x0c\xdc=?j\xb9\x00G\xa2\xd2\xcc\xd4UU\x05AJ\xc6\xf5\x0e\xfd\x9b\x02\x1c`\x86\xd2b\xd4\xcb\x91\x97\x83G\xc2\x88\xf5Q\xcdA\xcf\xab\xa9\x81\xf1\xc3\x96\xce\x15\xc6\xda\xecc\x83\xfb\xea\xbdW\xcb\xef\xa9\x15\xe8\x03WSm\x08\xdd\xc0\xadg\xb3\xba\xdaF\xcb\xf1\xaa\x91&\xa9^\x16\xf5\xfa\xd8\x98\xd4\xa1\x886;C1:=\xdb\x88P\x89\xe4\xba\x14\xd5`\xca\xda\x9c\x90VV\xff\x93\x1d\xd4E\x9d\xc65\"\xb4hO\xabX\xe0~\x14\x1b\xab\xde\xd8N3_5\xd3\x81]\xbaz-\xfe\xad\xe4\x92CW\xd3\xddt\xd4\xa5\x8d\x82\xd3\x88\xb4\xd0\x18\xcbe\xdc]\xb0\\\xb6\x94\xa9\xbf\x1dV\xaf\x19\x13\x96\x8b\xffc\xd4#\x1dm[\xc6ku\xde\x97\xad_\xca\xb1\"\xa9\xc9\xf6s\x8dH\xb3\x7f\xf4<}x\xef\xb1\x02\x85m0b\xe5x\x01H\xd3qb\x1f\x91a3tf\xe7MT\xdb\xd1\xcf*]I\xbb\x18\x1c\n\x15\xde}\xd7(\x1c\xfa\xbe\x9c,M\x94\x84\x8d\x96=\x8a \xdd@\x8cJA\xdb\xc6\xd0d\x89\x90\xa0\xac\xcb?\xc2\xa76PV\xb1\xf6[\x0ddV\xe3v\xf4\xe64j\x9e\xd2\xdf\x9b\x91lH\\\xe2\xf7\xd4\x16\x8c\xc5\xe8{\x98\xd8\xf2\x02M\xf4\xe5\xbd\xc8\x98\\\xba\x9d\x8d\xe5\x01Y\xfe\xdc\x81\x80\x1c\x1d\x81`9M\xc3`D\x13b\x87<\xc1\x05\x12;a#z\xf2\x86\x91<\x8ax\"\x06\xf3,\xa8d\x82gCi\xbf`\x91c\x92\x9b\x16:\xc1\x01\x05\xc8\xe2I\xb4\xe2>jw\xb7\xcc}J\x05\xc8\xc9z\xa7\x8d^:V.\x1d\xfd:\xd7\xfe\xda\x8b\x13{\xbf\xcd\xbc\x06(\xc8\xb2B\xf7\xe6\xcb\x1c\xc9\xa6\x03\x92\xc9\xf3x\x8e<\x18\x1eDb#\"S\xa3\xa1{\xf4\x92P\xf9Hu\xbdN\x81/\x13\xeb{r6\x05;wU\xb6\x13\xe6\xd0\xf2\x12s\xd6P\x17\xd0\x9e\x93<\xa4\xe7X\xc0\xe0Y\xe2s\xd4\xc4\xf7\xdeMxu\xb0\x87\x14\\\x9ab\x00\x91\xdas\xb8$\x11\x8e\x98\x11x\x8e\xca(\xa2\x89/^|\x03^*\x180j~m\xe0\xac;#\xb7%J\x84\xdeM4\x9d\xc7p\x98QM\xd7\xac\xf0::\x1ab\\C2gf\x01\xb0\xb0]\xbdz\xd2P8T\x99 U\xaa\x93Qb\xd6\xe8t\xba\x83\x1dC\x1c\xbdT\x9f>\np\xa08+6g_2\x96l\xce\xa16\xa7H\xf2\x11\x08 \xda\xce\x00\xc7\x86\x0fH\x9d:\xf7\x0dd\x9b<\xe6C\xcd\xe96\xb3\xaf\xd8\xa4\xea/\xab\xbf6\x7f\xe3E:\xc2K\x8b\x94\"\xcb`kJ\xa9<\x9b\xcf\xc6\xa2\xe4=\x08\xf9v\x9e7\x84\xa5\xe2N5\xb7\xb5`\xb0\xf2\x9b\xb6Jt\x8b\x12\xd9\\j\xb96\xcd\x85%\x03\x0e\xcb\x9e7\xf4*\xa5'\x0f\xa5\x10\x95U\x95\xd94\xb1:\xe2\x1bX+\x0d\xe4\\\x02b\x00\xfc\x92E\n\x11\xe4\xec\xf4\xdeaf\xae\x8ax\x8c\x1f\x93}\xc1\x891+p\x99\x8bB\xa5\xcb0\xee6\xf2\x17\xe2\x94\xe5\xfd\x9e3r\xf5A$\x1bN\x14\x9a~\xb6\x12\xf4#\xb3d\xaa}\x08\xc7\xd7\xa4\x9fP7h\xf7H7b\xa3F\xaa\x9e\xc2\xa7\x85\x82\xac8\xf0\x11\x0d\x1e\xb3P>\xf8Bt\x19\x1eGN\xd0\x14\x15\x8e\xa2\xf0m\xe4\x01\x82x\xf4@\x8fj \x85\x91\xb8|{\xc0s9\x12\x19\xe0\xbb=\x0f\xfewR\xd9/\xad\xaboDJs5\x16z>\x93;\x8a'x\xdd\xf1E\x06\xd0q\x15^\x06r\xe9^=G\x1a?\xbd\x859A\xea\xa1\x06\x7f\xe6\x96\xc7A\xe4_\x97\xa3\x06\xedK%\xb5D\xc9\xae:uikjk\xeeI\x18e\xc9\xe6\xbd\x1a\xacG\xfa\xd5\x9d#*\xa1\x86)\xb5jm\x06\x91\xe1|\xbdt\xa3\xb9}`\x01J\xe6\xa9Z\xd8\x88\xe9\xd6\xf7\x17\x07\x03H\x0f=4\xee\x9d{g\xdf\x81\xa2\xbe)\xa1qX\x88MA,\x17\x9aH\xf8\x8c7\x18\xfb1\x89\xebV\"\xa5\xd9\x14\x0fo,\xe7Y#h\x12\xfd\xfc\xf7\xdd\xa8S\x17\xf2_\xea;\x8b\xcda_\xd4\x97Z^cn4\xa2\xad\x10\x8d\xa0\x82H\xb8E\xab\xae?\x89\xab\xb0\x11}\xd1\n\xc8\x9d\xa1\xbb\xad\xdc\xee\xbc\xd9\xa4=}B\x9eWv\xde\xaaUe\xf0\xe5h\x9a\x17\x83\xda\x00G\x1d\x8a\x93F\x90\x85\x89\x91\xe6;\x9d@2S\xa5\xd8\x01\x9c\x80@\xcbf \x05\xfe\xc2\xcb\xfcn\xcd\xe22\xd0#\x8d\x8e\xe6\x1e\xb9\xf1\x13f\xddY:]\xbfJy\xe5\x08H]\x1a\xad\x95-\xb7\x98G\xd7\x8cwgv'\xa1\x07\x04\xe2|\x88\xc40e\xf1\n\xc3_7\x88\xf0\xd2\x90\xabn+f\x1e\xdf\xd9\xb8\xe2\xe0Y<\xab\xe7(\xcd\n\xaa?\xf6\xec\x92\x10\xa9\x91y\xf2\xf9\xa1%wm\xac+j\x0e\x83&&!\xe8\xa2c\x93^\xa1u'\x9db\xfc&\xf1h\x9fm6\x10\x04\xc2\xa4\x9a\xce\xfb\xb9*2\x0c?\x1c\xb4A\xc7I\x1c\xab\xb6\xc6\xb25F\x06W\xbe\xd8\x99[\xe2\xc6\x9c\x06\xa8B\xf5Uz\xefI\xceE\x94\x93!\x92m:\x8b\xd2\xfb\x9cxh\xd4e\x97\xdd\xc7\xaen\xbcz|]%\x0c\x8d\x90m\x11\xd9r\xc1U\xb8F\x8d\xda\xaf\x90\x05\x94\xf9\x11\x7f\xae1\xc6\x0b\x1d\x89};!\x0fn F\xbe&\xa0g\xf2\xda\xf1\xffP\x89\x86\xdd\x01\xaf\xaf\x1b\x1b;&\xd7\xf6\xa9\x9c\xf8\xef\x18$$\xb8\x1a\xe9F\xab)\x1a.t\x9bB\xedQ\xa83\xa6\x8e\xbd\x15(\x9eC=\xfa\xb7\xd3\xe4\xa6X\xc0\xce\xd8es\xd4;\xddi\xfb\xab\xb6\xad\xd9\x8a@\xbc\xd1\x08~\xfcN\xed\xc9\x1b\x1b\xce\xa1E\x01\x7f\xeb \xd4SR\x8b\x14\x04\x14\xa1\x88h\x9d\\\xe9\xe8\xa3\xfa\xc1Be\xf1o\x18\xba\x86\xbd\x9c\xa0\xb4\xb9\xce\x01bT\xd1\x16\x84\x06n\xce\x92\x11ju\x02\xb9\xbe\xc0\x1b \x07g@\xe4\xf7'\x04qQ\xeb\x94\x8enx.u6bVU&\xd4\x0c\x9b]\xb9;\xdb\xef\xaa\x15!C_\x0c\x84\x16\x06\x0b\x08\x9e\x8d5\xc6*\xdez\xb9\x1d\xc9\xba\xfbm\x80RQu\x91\xaaq\x82\x92\xe0\x16\xa6\xb1P\xfc\xdaZ0\x83\xb6}m\xf1\xbc\xa1\xcc\x06\xca\xf5n\xbd\xa6^n\xd5Or\xc9T\xa6\xe2\xc1\x91\xb5\xce:\x9fU\xe3'\xd7h\xc0\xe6\xa70n\x0fZ\xa1p^\x19R\xe9|DF\xaa_b\\\xf2@\x96\xd6m\x81\x82\xe8DE\xeb8\x81\x00\xc6{o\xe8\x1eGM\x89\xe1\xa0\x9c\x01q\xb8\xdd\xcf\x06}\xdc\xeeSd \x16\x14\xae\x0fC,\x1b\xfb\x04i\xc0\xdc\x9aE\xea\x1d\x12\x8a\xe9/\xb0\xde\xc3\x8b[\x18d8]\x8e\xd7,MCI\x9a\xce\xd0\xf3_u\x97,]V\x99\x81c\xf1\"\x97\xe4\xa4p\x18\xb0\x06g\x1d@\xec`\"y)\x8b,;B\xb3^e\xad\x9el\x10\xda\x08\x04\xa1\xaa2'\x80.(\x9d\xcd\xd0\xc4\x98\xe2y>\xe0-\x1a|\xceh\xad\x18\xdc\x13\xd3\xc4w\x9a\xfa\xfe\xea;\xa9j\xe5\xa5\xe8\x1d\x92\xed\xd5\x8d\x18\xd1\xd2i\xd4\xbd\xb1\xe4\xaf\xea_\x19\x08o|!@\xf6)\xc9\xa2\xdd\x1e\xaa\xc4=\x7f\xd9\xcc\x8cSPz\x9d\x97\xe9\x1d\x1f\x88*!z})\xbc|\xc6\xa7T}\xbdj\x18\x91\x86E\xa3tC\xacZ\xe5\xa1n\x8c\x8d\x17\xbd\x7f\xc3\xbd\x9c*\xd5\x9e\xf5\xc94\xdb\x86\xd7\xbd[\xb9\xa9\xb1\x0b\xbe9\x1a\xbb\xd0\xae\x05\xa8\x8e\xe8\x88\x17\x91\x06\x92\xdd\x93\xf5\x8cz`W\x08m\x14e\xf4o\x82\x8b|j8j\xad\xef5\xe1\x18\x909\xbc\xf6\xb5@.\xfa\x9aE\xbf\x18V\xcc/\xccZW\x05@\x17|\x97\x81f_\xe7\x10\\\"$\x1d{\xe1\x05\x9c\x91v\x10\xa1\xe0\xf2\x83\xf3\x9c\xc0\xc8/\xb8\x06\xf2\xb6;a\xd7\x16\x1c:Se\xa6i3T\xe4G\xcb\x10*\xeb\xce\xfd\x83]\xb8\xc6\xa1/\xcch\x14\xc02\x1dC32$\xbf\xd3\x01\x0e\xf4\xbf\xfc1}\xbf\x8cD\xa4\xcdNX\xc9\xf8\xfet\xec?F\xcf\x9d\xed~n,Pj9\x0f.\xee\x96>\xd7\xa3\xfc\xa8\xcd{\n9\xfd\x7f\xc9EN-v|3h\x86\x14\xf2\x91C\xc5\xd0\xb8E\x94\x95\x87 XT\xe0\xe2\xcb;P\x96$\xc3=\x8dJ\xd6-\x0f\xdd\xd5g\xdd\x95\xfd\xf9igz~q\x97(A\xe9<:h\x131\xb19\xb33\xe1N\xec\xcc\xbd\xf5Q\x89\x8b\xe3\xc7}CL\xd8\x7f\x90W\xf9\xdf\xa7\xc2\xd7\x8e\xdc~\x83\x12\x1b\xe1\x0d\x12\xdab\x99\xa5\"\x86\x81\x87\xcd|\xc74u}\xee\xf0\xad\xd7\x01\xd9c\x99y\x80\x04\xe0\x8b\xc86\xb0\xa12\xff[ \xa5\xd8\xd6\\d\xb8,\xb5\xd2\x8e\xd5\xb3b\x81\x11k\xf9\xa4\xccD\xe5\xe4\xbe%0T\xdcx\xad\xae{=;\xf6\xd4\xb7\x8b\x86\x01(\x84i\x08\x87\x0b\x8d\xd8LS\xb7\xf8\x13\xdf1\xbd\x98\xf8\xfd\xa9\xd13\xffN\xcfh/\xa46?\xe6'E^\xf6~\xff\xc6\xd4P\xae\x7f{sZ\xec\x1b\x99Z\xd3K\x94\xc4\x9e\x13B{\x92D\xcct\xf8&\x89\xbd\xd4z\x92\xd3\xf7)\xb5\x17Uoa\xf95Q\xa63\x8f\x91\xc8\x97\x88r~\xbf\x8e\x91\xbe\n\xa6\x01\xf4\xd9\xf9F]\x11\xa0$\xba<\xe8\x04\xfatm(\x9a}\x0c\xfb\xc3\xcfMB@\x87\x9e[\x9cGx\xec\x08\xceF\xd3\x05h\x108\x00\x9b#}\x88\xf4,\xa3#\xc0\x98u\x0b\xfdLaz(\xdeQh\xb14%\xd3x\x01m\x04`U\x13\xe0\x95\xd5\xb9.E\x11\xa8\xe3v1a\x92\x9e4\x0e_'/[\xa8d\xb1{Fx\xa8I\xca59\x9e\x8c\x0c\x83D\xf5\x11<\xea\xec&\x908V\x88E\xf3Fg\xc9\xc8\xd9\x0b\xe8\x8a\x98#\xf5I\x91\xe4\x9f\x8d2S\xb2\xcd\xee\xff_\x06\x0f\xe3\xa9]QqA\x13\x9an\x88\xd1_\xf0Q\x19\xe7\x07\x12>b\xde\x984g\xa1\x19\xa8\xad\x13\xb1-\xae\x010&\x07E#c\xa6\xdci8\xbf vR/\xd54\xff\x18r\x9e\x8a\xeb\x08\x9aP7\x95\xa3K\x03sOW\x05\xb5N3\xd5\x8f\x1evE\\bq\x86\x7f\xfbQ\xdf5\x18\x12\x8dZ\xb9\xda\xbdVy5\x07]\x8d\x13\xbd\xd6\xf6\xe0h/ i)\xc5\xfb\x9d\xa6\x8e-/\xb4\xb0\xe3\xa1k\xb5N\xac\xd1\x8e\xbe\xc8\xc4\x1c\x13#e\xec)\"P\x17\xed\xf1\xfc\x08 {\xfdKSQ\x90x\x89\xb2\xb8\x9d\xa6>a\xe3&\xb5\xed\xb6\x8e,\x84\x17\xa0\x0e\x0d_\xe8g\xa5\xb4\xf1-m\xe1c<\xd7\x18n]\xd0\xa7-\x14\xae5\x912c\xa8\xb9\xa1\xae\xf1z\x0d\xac7d P\x9cz\xf3\x13\xe5\x01\xb5\x19\xe0\xf2\xf0\xb2V\x84\xf6\x93\xfb\xa5O\x1dPvf\xbcR\xfe\x0cR\xa4\xd3\xc6\xe0\xb0\x939\x86Z\x0d-\x9f\xc1\x1e\xded\x12\x86\xf7\xae\x9a\x88\xbfC\x9b\x9a\xf1\xf3\xc7`,\xf6at\xc1=\x13\x14\x87k?v\xa2\xed4#P\x0d\xe8\xa4B\xcc\x16\x08\xa1\x9a\xd8\xa5\xb8/[\x17\xf5\x06s.-bH)\x11\x11\xc9\xbaz\xef '}\xb6\xd7\xb6\xdd\xeew\x9c!\x04\x17r\xc1X\xce\x11Z\x8a\xb5 \xb4.:\x92Vn\xd7\x13;\xee-\xee>\x8a:\xe1\n\x1d\x026\x01\xe0r\xff\xbd\x87\x0e\x1dU\xc1cs\xd54k\xac\x11VW\xac{\x92\xfa\x89\xf0#\xad\x0f\x985\xdf\x910\xc1B\xdd\xe3\xec\xc7`\xdc\x9d\xff0u\x9a\xd1\".Q\xca\xc6\x1f\xac\x9bdB\xb4\x980\xa3\x94\x1d\xf5\x98C\x9e\xd0r\xf5\x1e]\xed\xef\xe0#\xed\xbaQ9\x08lq\x9c\xe0\x02N^\xf4\xd6\xb3\x8d\xaf\xe9\xf4h~\xa0NU\\\xb4 \xbc16\x9a\n~\xe9\xe8\x15\x93\x1c\xe1\x94S\x91n\x87T\xf2\x04l\xa2\x91\\\xfeTH\xd2\xb2\xda\x9b-\xd9\xc9~\xaaG~)$\x85oQ7\x1e-\xeb\xafC\xef\x11\xb0\xcc\x01\xc8\xec}q\x12%/\x1ca\x99\xa6\xb3vO\xb0\xaa|[q4\x96\x82\x8a\x92\xb3~Bc-$N\xdc\x1b7\x9e6\x1c\xbd\x9f\x90w\xd2{\x0f\x9cV\xe9\xa4\x83.&\x13\xa3\xf6(\x86\x0eo\xb9\xa9*\xf5n<\xa7\xd8n9\x06\xa1\x06\xc1J\x96\n\"a\x87\x07\xa9\x0b\xd0\x94\x08\xcd\xdd+\xa1\x86\x0ba\xca/\xbb\xfd\xba\xba\xf0;7zD\xd8Z\xce\xb7\x11{\xd7t\x8fM Mp\x97\xa3 i\xd8\x9ak\xbcNPw\x88\xd8\x91\xcd\xba\xf0H`T\x0d\xf6$23\x1b\x96\x86f\x1e\xd3\xf6\xc0\xd0\xda0\x9az\x1f\xc6\xc8;\xad\xa1\xa6\x9e\xe7\"\xf0]\x8c\xf2\xaa\x82*\x8eY\xb2\xa4\xe9\x10,\xe4Q\xa1W\x81\xd8\x1b\xe0\x0e\xf4\xb8lS\xe9\xb5\xc6\xc5O\x8erW$5\x06]K\xa1V\xd9\xbbB\xe2\x16\x85\xdc\x9a\x85I\xb8\x18\x8a\x18k\xda|\xdf=\xb2&\xc1[\xd4\xe8\xea\xde\xd1\xde\xc558E\xd3R\xa40\xde\x8bGk\xabs\x1bS\xee\xf1\xc1n\xe3\xf2n\x11nu\xe3\xfa\xf1ExK\x8d\xd0\x7fr\xf4\xa2\xac\x8c}\x87~m\x1f\xf1\xd9`\x10\x8eG4\x02u{\xd0\xd1\xf1=]6f\xa4\x00\xf7\xe2\x08\xd7\xa8\nBo\xd6\x1e&<\x0d\x99\xc3\xb1c;2\xa0\xae\x10P$\xc3\xc7\x83{mW_c\x1b\x9e\xf5\xc2\xaa'B6\xd0\x8a?$\xbd^z[\x8fC\x03\x97\x1dY\xb9\xdd\xad\x99\xe9\xa5j\xd0N\xf3~\x0b\xfe\xa6\xdb\xae0\x05\xbe\xbb\x9b\xfat\xa2\xaf\x06\xfa\xb0\xdb\xe2\x846/)-\x891\x7f:p$D\xea\xa5\x85\xc8\x97\n\xae\x10\x1a\x0e\n,'\xb3\x86\xfcy\xe0\xf5\xb1\xf8\xc1v\x98\xc4 \x85n\x9c\x8bF\xb3T\xd7\xd1\x81\x99[\x04'a\xa6Mb\xceJ]\xbb%\x90&\xc3\xae\x10\xaclc6\x02&\xc2\xe8IpF\xe5\x90\xc4\x0d\xa8\xdco\xf0\x8ci\x83\x06\xaa\xc4\xc9\xfe\xe3\x155\xb1\xa0\xf8'r\xa8\xe4\xcb\xe5r\x91(q\xbc\xef\xe8\x90\xfa\xae\xeb\xee\xbez6\xc1\xb0\xf6\x9e\xee\xc9(5\xf3\xd0\xe1E\x0e\xf4\xe0\xc9\xa2\xd5\x9fl\x13\\\x1d\x85L\xf1\x9dk\xba7\xab\xb01\xc5Y4^)\x02b\xd9\x97\xc2\xa68\xf9\xbcy\xf8\xc6\x8f\xaa\xe4\xdb\nN\x9e\xd8=\x83\x9b9zT\x96^[T$\x87dk\xc2\x19\x9c\x0dQ\xe2iK%\xe1\x886\x8e\xb5\x90\xfcq\xb5\xe9\xe7\xf5\xcc\xeefO|\x03\xe0\xda\xe0c\xd08$\x95ji^v\x1b\x04r\xfe\x02.QQR\"\xe2Y\xe1r\xc4\x8a\xe3\xe2\xf5\xb8\x0d\xa8\xc3k\xf8\x92\xa5\xder\x9f\xba\xbcK\x0e\x88\xa2\xb5\xfb\xa0\xe6\xe8\nN\xb7e\xed\xcf\x08Ri\x13\xfb4\xa6\xbe\xd5!3R\xf9\xa2\xba\x15\x90\"\x8d4\xa6\x88\xc8\xf1\xfa\x9an\x99b\xe1m\xc9-y[X\xa6\xa6\xff\xcf\xf1.\"\xc6\xf4\x19!\x94\xf8\xdcQK\xaf\xe5E\\\x07N\x8f\xeb\xb54g\xd5\xa0\xd7\x9d\xf8\x05\xa7\xbf\xa6\x83\xef\xb1aN\xa6p\x82\x0d>k)9\xc1\xc10\x88B\x8dZ\xea\xccBs\n\xf6\xa5y\x8a\x19r\x8e\x9aer\xab)v\xaf\xa2\xaeD\xf3\xebt\xe8rv\x81\\\xfbv\xf9[\xad\xfc>\xf3r\xb5Jm\x9c\x81\x02\x96\na\x9c\xf2\xab\xb5\xcc\xbc\x9b~u\xdd\x17\xea\xea\xd5\x8f\xba>\xb5rMZ\x9c\xb0\x98c\xedB<\xf8\xe3\x0f`)\\y\xd7t|\xdb\x8d\xef\xffr'<\x86\x18\x1a\x06\xf4\x98\xe0>\xf9\xd7\xd6\xfe\xe3[\xe6\xc3\x8e\x97\xef\xad\xe8h7\xeb\xfa\xad\xfeZ\xc5\x10\x04\x8c8\x7fcaI\x81!\xb9\x0d\xb4p\xe2\xa2\x9f\xcd\xcc\xae\x00,\xb6\x0fG\xc3\xed\x0b\xbbk\x07\xa05@\xc8\xd9\xf4\xf7\x08\x1b\xff`\xf4\xc9iw\x0d\x88\xd2n\xd0\x9e\x1d8p\x9fv\xbf \xe7\xc9\x13\xe9*\x8f\x9d\xb2\xc2'O\n\x0b\xdd\x1d\xd4\xfc\x8a\xb2\x14\xa0\xddA[\xc8.\xa1\xa4r\x8f\x16h\xf3T\x0dpR?+;\xcb\xff\xf3\\\x11*H\x8bsLq\xde\xe6\xebU\x9a\xb9f\x96\xe2:ql-\xc4\x87\xa4\x0c\xf1*6!\x85h\xe7+\xcb\xac\x04\x00{h\xb7\x89\xf6- jg\xb1k\xc9MM\xc9\xd7P#\xe3\xb6\xe4:\xbc}\x91\xb1\xb8{/\xdd\xeb\xeeV\xcb\xdf\xc5\xb6C]\xec\x98\x99\xea\xb7&[\xb3W$\xda\xab\x01\x03^\xdf#\xe0\xfb\xb8\xb64f\x1dWa\\\x0d\x8b\x05\xc15\xec\xf0\xe8\xba\xbaM[6\x9e\xbd\x1c)T\xa73\x97\x95\x1b\x15\x9b~\xfc\xda\x1d\xce\x0e\xad\xc9\x12\xd4\xc0\n\xe3:. Z\x94\xa6\xbc\x02\xa8`s\xdei(\xcdR\xf4\xa9Q\x85\xbc\xb2\xcc|/\xfa`\xf9\nil\xcf^\xb0L#\xa0\xa7\xf7\x1d\xf2f\xa4-\xf1\xd7;-C;\x13_\xdc\xde\xf9*\xf9{@EMCoo\xc3\x82_\xa4\x9c\xc6\xc3\xf57\x17\xbeT\xf6\xe3rqz\xdcF\xb5%\x17\xd7\xaf|\x99\x9aUE\xc6\xabUs^\x14\xdd\x9cv{\xa0\x7f\xeb\x04\xa4\xa6fQ<\xc4\x90\xa1\x89VP\xfc\xef\xc3\xcaT\x0ef\xcd\xa6\xee?\xa5\x90\xf5m\xd8p\xd9P*\x00\xc8&\x01\xa6\xf7\xd0Q\x87G\x89\xf9{c\x9c\x03J\xef\xf1EP\x18e2)\x8exP\xbd0\x05A\x06\xd1\xdf\xcd\x01\xfbM\xc9\xaaZH\xb6j\x95\"\x11\xd7\xbb\"\xd9A\x05\xac\xd0C+zq\x89m\x04V\x11z\xe1\x96\x9e\x05\xf3U%\xd8C\xb5\x00:\x16@1\x0e\xe6\xe3\xf0W\xb9\x8a\x0c\xee[\x11y)\xceJ@\xf7o\xb1b%\x0c\xf7j\x94\x15A>)N\x0f\xd2\xc7\x80\xd4i\x7f\xe7\xbc$\x92A\xf3\x88\xc0\xect`>\xcc?f0g\x00\xffH36p\xe86\xe1\xccD|\xfb\x04M\x9b\xe4\x0c\xe1\xf6\x104N\x8d\xa1\xb0\n\x9c\x92 4J\xbdJ\xda\x83\x1e\xaf\n\xb5j\x07\xa4\x9e\x98\xc6\x87\x01\xb4\xf3\\\x0d\xedp\xa03\xd3\x19\xf8\x1c\x8e\xa38\x8d\xc0\xa6\xaa\xd1\xe3\x96\xd0\xaf\xef\x94\x13\xbb\xad6p\xae\x11\xf9V?:\xac$\x82sD\xf9\xc0N\xfa\x12\xb5\x0e\xc6\xb9\x912\xef\x92n\x92,\xb6\x84H\xddO\\\x82[\xb8\xf8\xd5\xb8\x9b\xf6K\xd9-)\x9d\xabW~\xb9i\xe9m\x99?\x18\xff\xae\x83T\xd0:\xb0\xcc\xf0\xde\xbaU\xd6eY\x8c\xd3\xe3\x8a-#dJe)\xaf\xb1\xda\xcfZ\xaa\xd55\x94?\xf8$\xbb\xe6\x0e\xa1\\d\xa9W\x19<\xb7\xb9\xb9,\xc9\x86\x7f\x86\x9a;\xaf\xd8\xb7\xb8\xc35\xcd\xcd\xf2S\xb8\xd5\xb8\xaf\xbc\x1a\x97T\xabT\x96\xf1\x9a\xce\x08\xcc\x84f(\x81PY\x0e\xb0v=Q\x0d~DX\x7f*\x07\xbc\xdf\x0f\xdd8\xf8\xe8\xbe\xa9s- \xc2\x08\x05\xcb\xa8\xae\xce\x80\x0555\x02\x0c\xad\x0dX\xa2R\xa5l QC\xcf\x08\x18\xe1\x19\xa4\xce\x0c\xe1\x93\xf8\x03\xd1\xc0l|\xf2\xfd5\xce{\xfb\xd3\xa6T\\t\xea\xbc\x95+\xe9\xef\xa3e\xbbn\xc5\xdb\xb8\x8b\x92\xc2Ps\xd3\xe8\x1fl\xfb3\x15\x99\x9d\xf9UO\xa9[\xfc\xdb\xee\xc7Z\xbb\xc9S3\xe5\xc0\x9d\xee\x9f\x9d*\xe8\xec,\x98\xaa\x86\xdf:\xc3\x9bZ\x1f\xfe\xbe\xc6\xd4L\x89\x9b\xac\x86\xd5\x05S\x9d\x9d\xf4\x15'\xcc\xb5\xe6\xe3*\x07\xf5\xf2\x8c*@\xa8\xf8\x19\x9d\x1f\xc4\xb1~xgno2\xb1\xb9\x19\xe1\x16\x88\xe2-\n\x85\x8c \xb3W\xb3\x14\x8a\xab\xbdV\x1c\x00;\xe4pZ\xe5\x049\x8d?\x13~\x84\x18\xab$\xab6\x9f<\x94\xb5Qr\x82bQ8&\xf3\x14se\x1b\x95\xc9Eb\xaf\xdaQ\x14,\xb7\xfe^|B\xb2\xb5\xef\xe7\xa2\x98\xefVd\xacV-\xb6(\xdc]\xe3 .\xef\xe8\xcb\x8e8\x1f\x12/qhV\xa1\x1bnR\xae\xf3\xaeQ\xc8D\x89*\xf9U(*1h\xe71\x14\xc3`\xd8\x9dQL\x12{\x07\x85\x81Uj\x0b\x0b`\x17\xe0\xd2\"\x9ao\x1e3\x00\xdc\xbb\xe6\x99V\xa8\x02l\x05\x85\xb5:\x1c \xd1\xed\xea\xc2\xd8\xc0\x0dja\x04Fa\xe0\x10\x9eE\xad\xb6\xcc\x9eZ\x88\x8bg1\xb1\xb7z\xfc\xb0\xcc2\xd6\xa0\xd5:\x04\xcdAu\xd9ZIf6\x96\x83\x012\xd5tw+\x08\x8a\x89\x89\x17f\x19\x81\xa7D\x8f\x8b\x1e\xef\xc9\xe8\x11\xaa\xa9\x11CL-}\x14g\xbb\xb5Z\x18\xb30>\xd2\x84\xf3xJ\xa2\xfd\xff\xc5>\\\xee\x90\xc1\xebQ\x89\xb8A\xda_C\xb6i\x82h\xdf\xd2b\x0fl]\x0d\x05\x1a\x876\xde\xd5\xde\x1d\xdc4\x1e*\x0e\x9aA\xcb\xaf\x16\xc9\xb0\xfcqX\x89\xa4\x047\x84\x1b\xbb\x14Y\xf2X.\x80-\xbe\x8a\xda\xd5\xb8\x95a\xc9\x87\xc3V\xe2h\x17\xac\x96iKg\x95\xd4\xcfqN\xb3R\xc4\x86N(r\x11'\xc1]\xbc\xe0%\xd9\x98\x84\x8f\x85\xad\xf4\x8d\x88@3\xd4\xcd\x80\xce\xc2\x81j\xa7\x16Z\xac\xf7J\x86.\x1f;\xfc\xe3nm\xdd\xfa\xaf\xd5\xce,S\xfb\xfb\xd8\x040x\xaf\xb3\xc3\x1f\x01\xf5\xf8\xd8\xcd\xbb\xa3OF\x0733\xad\xd2\xa7\xb6\x85\xab<$'\xdb\x0e\xbb\xb8G\x97E+\xb4\xda}\xa5\xa5\xce\xf3\xfa\xf3\xa7\x85'1\xf0f3\x9b\xc6\xfd\xd2y\xd05\xdd/&\xa4Z\x9c\\\x1aRB\xf47dm\xed\xf4]\xe6\xbc8\xa7\xa7\xc2\\\xcd\xfd\x01\x843\xdf\x82\x84\xc8\xaa\x98@\xf7\xeco\xbf\xfbT\xe9\xbf3eu^\x12\x1d\xb7W@\x8a\xaa\x15\xfc\x94\x96\x8e\xa6e7l\x96\x1e\x07!B\xe3,\xc0s\x82\xe4\xe61\xdc\xcd\xdf$\x9a\xe4\x1b\xf2\xaf\xdbZ\xa7\xe3&\xd9\x14\x92\xe7?\x03\xaf\xe2dC\xe9\xe1 \x9d(Y\xd0\xa6Sm>\x82J\"&pt\xde\xdc\x88\xaaP\xe3\x87\x84\x03B\x1b\x01F\xac\x14\xf8\xb4\x9d\xda\x04\xb1\xe0\xd9\xf84\x8cG\xe15\x9c t^\x1d\xc4\x86$\xaf\xde\xf2j-a\xe3\xa0\x8dg\x1a^\xc1\x0e\xca\x90C\xa4\x12\x96\x85\x83A\x02s\xd6T=k\xa1TS,|\x0e\x80r\xe0\xe5\x0f\x9a9I\xb7\x0f\xbdB\xcf\x98\x07\xd0\xac\x86\xf6'\x01\xc2\xecvG\x00A\xb6\xce\x11@\x90\xcdt\x04\x10\xc0\xcchQ\xd5Nj\x86&\x18\x80\x05\xe5T=\xce\x03xt;2]\xaf\x12P\xa1|T-\x07 L\xc3\x9e\x83\x92\xc9\xe7\xbf\xf1e1\x14\xe3\xdd\xbd\x04W\xc3Z\xc5\x9a*MrH5?\x84\xf1\x82=\xe0\x00\xfd\xd1o\xb0\x03\xac\"\xeb\xc69\xd1K5\xce\xf8=\xab'k\xc9-*\x07\x95\x84\xe8A\xa6\x12\x0f\x16E| \xfe \xde q\xd2\x94\x13\x91_?\\\xa37%\x1e\xf6\x8e|M6\xb0f\xaa+\x93\x93+\x92S*}\xe7W\x00_\xdc]3\xaa\xa8\xfa\xb6fm\xdc\xae\xd8\xd2\xcb\xb3\xd2\xdcm w!\x96\x97\xee\xf7\xe5.\xdbR#\x89\xe9\xac\xaa;\xc6\xed\x1f\xfa\xa6\xb1q\xa0q\xf371\x8a\x01\xd6\xe4$\xc2\x95\xdd\x99\xd5\xaf_\x19\xc0\xf3iK\xe0&\xecJ\xa9\xce\xacM\xae\x8a\xac\xf6\xde\x1a\xc7em\x12\xe5V\xc45P\x7f\xcf0>\x14\xbe\xbe Q\x9d\x15\xe7\xb55\xaa\x86W\x95\xa9H\xadIh\xd7\x1a\xe5\xf9&\xf94\xd2\x8dIl\xd3E7}\xe2s\xc8\xe9\xc4m[c\xc8\xbe\xec\x01\xa2\x84|\x8dd^ \xa2\xec\xf7%Uv\xe9\x011\x0f\xa6D\x07\x93\xb2>\x93.\xe8T\xac\xd2\x1b7*\xe9=t\x83Z\xb8_\xa7\xe3\x9f\xbe1\xd0\xa5:=0pZ\xfb\x9a\x066\xd2\x8b\x8aN\x04\x84t\x17\x14\x00(\xe5\x17u\xed\x0e\x1e\xc6\x9d\xad; \xc7B\xd2]\xb3\x91$\x80k\xa1\xda\x8c\x80\xc2.\xf3{\xaaF\xc4*\x03\x12/U\x1dZ\x92\x1f\xc6N\x08\xfc\x12\xe7\xa0\xa6|oq\x8a\xca\x15K\x97G;^\xd6\xe4\xbe\x9e9N\xa7\xfbe\x1f\xff\xedxK\x8b\x0c\x92\xa1\xa8\\\x87wh\xfe\xf8\xf1~\xa1\xf2\xf2Z\x02pH\xd4b\x91\x12\x8b\xcd\xe4\x89\xb8\x1e\x0c\xbb\x88\xdb[k\xb68\xe2\xc9\xcd\xcck\xf7\xe2.bX\x0f.Q\xbeXp\x02\xb8x\x0eYa^\xb5\x18\x02\xd0\"\x98\xd1#\xeb\x9f\x18\x99\xe3B\xb3\x10wnb\xa4\xbf\x11\xf3\xe5\x90u\xd3\xf0\xa0\xe9m5\x9eF\xb2\x0f\xbd~>\xc7\xd08\x1f\x05\x80\xad\xc1b\xfd\xfa\x8e\xe4N:\xddp\x1b4\x0b\xb5\x01[gv^\nB\xbd\xd3F\xd0Uz\xfb)?\x9c\xbc60\x8f\xd0F\xc9\xc9\x078\x98\x82\x00\xc2/\x042\xa0\x8cC\x088\xa8\x8c\xae>\x18\x9dN8G\xee\x8f\xcd%\x10l\xf3%\xe8\x1f\xdd5\xbaFH\x98{4\x846h\x1c\x04\xa7\x8e\xef\xb84\x8e%\xc6\x01#\x0d7\xb8\xe8\x9b\x1d\xf1\x8e\xcd\xfa\xcbx\x0c\xf3o\xba\xdcN t\xaa\\\x95'\xdf\xc8\xa8\x0f\x0d\xa8 \xfa\xe6E\xa3\x8d\x8e\xe6\xbd0#\x83\x12\xefj\xb8N\xc3\xa3V\xef\xd3\xb9d\xe0?WlcW\x90\x81\xd7\xf0\x8b\x0b\xc4\xed\n\xc5\xbe\xbd\xd6\xb5\xb5u\xfb-\x93\x06\xbb}\x0f2\x842\xa8\xb6\xa5EN\x90\xbf}#\x87\xe4\xb5\xb52H^a3\xf0\xf5\xbb\x19\xa5r\xbb\xc1qs\xa7\xa4\xb0\x88\x84-\x8fS3&\xc8\x04\x14\xef\xf4\x84f\xb4\xed\x87\xa3\x0e\xcc\xeb\xcefwl.\x9a=W\xf88\xe5\x84,\xf5\xe0\xd2cH\x03\xe1\xaej\x9ecT\xea\xb1W\xae\x0e\x91\xd7\xa0\x05s\x819\x0e\xf20\x9e\xee\x94Z\xe0D\xceM\x11\x93\xfa\xbeC2\x92ZM\x92\x8d\xdd\xfb\x90dj\xb5\x8ct\x9f\x16\"8\xc0:g\xed{.\xc6\xb1\xb0\xd01Fb6\x831\xc78\"\x06y\xd4\xa6>\x98\xf5\xbf\x0c\x92\xadW\xc09\xa3\xeb \xd3V\x9a\x1a\x8a\x8a\xf6\x0b\xaf`\xd7\x12j\xbf\xfd\xae\x16\x9a\x8f\xbfT\xf2\x94\x94\x91\x91\x80\xb2\xb5r,n\x83\xa9i\xc0\xad\xc1\x0d\x0d\xa5\x16d\xb3\x85 \xff\xf4\xe9qN\xa7\xaa\xdd\x0c.g\x04+ \xefS\x07\xc2\x1a\xeb\xbc\x0dQ\xfa\xf9\xb7\x81\xbe\xeb\x0f \x0d\x81\xe1K\x02aB\x08\x01\xbe\x8c\xdb\xe0?_\xed\x8b\xdbQ\x8dE \x87\x93\xb5r\xb8\x86\xffj\xa4\xee\x82h>\xf4\x95E\xa6\x90\xd3\x9b;\x13\x8fC\x9d\xd7\xad7\x7f\x85\x8b\x1c\xb7^q\xaf\n\xc6`U\xafe\xfa#-\x9f\x98\x18\xb7;oJ\x98\xc4\x8b\xe3\xd2\xe6\x8e\xd4\x9d>)\x0b\xc7\xfd\x82;Jg\xed\xa3\xcf\x7f\xd7\xad9R;Og\xed\xa2\x1f\xc5\xfdiI7\xfa}\x97\xe28K\xa1\x92\x9c\x1f\xdb\x81\x04q\xa6j\x8f\xb9\xd1e\xd8\x93\xa3+\xd9\x97'n\xf1\xcf\xb7k3\x8b\xc1\xad\xbb\x07\xfceF\xcf\x81\x03\xfb\x05\x9e\xec\x0e\x850\xb1\x9a\xf2\xaf\xdfV#\xa9\xed\xc6p\xa5MAzb^P\x8e\xf7V\xcfu\xa4\xdb~\xde1u\xba\x97\xd2\x93\x95w\x1en\xc8 ^\x9b.II\x97\xa1\x8a_\x1c\xc6\xcc\xdavdW\xae\xc8\xf6\x8f\xf3\xce[Q,\xcd\xde\xe8+L\x0f\x04\xbeb\x82\x16\xed\xbe\xc9\x02\xa5\xe5\x84\xc6\xc4\x87q\xbc\xfe\x0d9\xabV\x1c}\xef \x94\xce\x8fV\xd1w4qU\xe43&j\xdb\xc4\xb1HYb\xbc \xfc\xb9\x88\x0b\x15\xbft\x15t\x8dT\x9c\xf5\x887\xcf\x81\xf2\x92\xab\xd9a\x16rBwP9?)\xdbu\x95\xe9\x8bT/\xd9a\xa3\x95\x8eA19\x96\x11\xb1k\xaaM\n\\\xd3\xe4P\xdd\xdfs\x9b<\xd8Ta\x9e\x8d\xd0\xe3@\x82\x85\x0e\xf5q\xb1\xd8+\x1c\xfb\xa3=\xd9[5\xc4\xcd\x94\xb7\xb6\xd6\xd7?\xb29\xa3W\xc0\xc9+^\xfdo\xaf^E\xe0\xe38s\x81)\xe5\x8ff\xe7\x0b\x972a\xf4\xe6\x01\x16\xadQ\x9f\x05x\x01\x1a\x7f\xa4\x17\xb7i\x87\xe9& NE>\"^Na\xe4a\x9f;f\x8a\xd9\xcc9]NE& t\x18^\xb0\xc0CL\x1az'\xe2e\x858ZR\xf1\x07s&6\xde\x02\xb27_\x00\x1f\xfc\xc3\xa3cyJ\x9e\x911\x1a\x0d\xc4\xfe@TZ\xb0?S\x00D2\xfb\n\x1a\x87|\xd4P\xf5\xd4\xcbO\xd3\x8c\xe9\\d\xaa\x1aR\xef\xde\xf0\xfb7zH\xd5\xf8\x83\xee\xb19i\xc8\x03\x00\x8bQ#\xb5\xbf\xb6\x82zr\xb3\xf3c.\xf24\xf6\x86G\xfdR\x9d\x134\xce\xc8qx\xa6\xf0\xbe<2~X\x92h\xb5\xf7n\x08\xe1\x19\xe3\x19\xe0\xa9\xb3\xa8\x06\xc52\x88auB\xadNC\xd1\x00+\x9b\xa2k\x97X\xf30\x0e\xd1\x0d\x18\x13aj5n\x03>\xde\x89\xa8\xf5\xb2\x12e3\xf6\x07\x11v\xde\xa7\x17\xd3\xf4\xe9<\xa5>\x81\xb0_\xb2\x9f\x90\xa0\x07\xdb\x0cuH:\xa0\x04\x90XR\x9d\xff%~9\xe1\x04!4\xf6\xfco\xd1\x0f\xd1\xbc\xa6\xe8\x1c\x02\x003\x85\xba\xe2\x948?\xb6\x82 \xce\x1f1\x01d\x1a#\xef\xd4\xd1\xfc\x1c\x96\x9aA&\x8b\x84\x84{A!i6\x0b\x8b\x8c\xed\xdc/Xa\x9d\x9f\xa3\x1a\xe1\x05\xe3\x87\xa4=\x12W\x16\x89;|\xef\x04\xf0\xe4\x1a)\x81 \xd0g\x16\xbe~\xa3\x0d?*\xbe\xe6\x82\xbd\xc3 }\xbf\xe3\xda\xa7\x88K\x11t\xcc>5|\xadE\x8e\xb5\xd0\xee\xd1\xdc\xd5.\xa7\xfd\xf4A\x07\xfb\x9a\x0bQ\xf16\xfc\xfa\x0d\x02\x07\xb2\x80\xbe(6\x1a\n\n6\xd1\x94\xc67\x00\x96\xda\xf7<9\xf9\xf9_\xf0\x95C\xc1\x0cf1\x0f\x19\xfe\xeb\xd0\x8e\xe9i8\x15\x06\xbe\xae\x86\xe5\xbb,\x0dV\xbb4$\xc0\x9fut\xc9\xf8\x9c\xf8\xa3\xc6i\xc1,.`v6r \xe2\xa3\xf2\x8eP\x0d\xaf\x1a\xbdgFB\x90\xc9\x8e\xc7\nt\x1b\xf2\xc3\xe7\xda\x0dC\x013\xbd;\x98\x0c\x1f\x04\x18,\xbco\xc3\x82\x93\xe6\xe3\x9cx| \n/K\xf3Mp\xa91S_\xbe\x91X.f\xf7V\x8d\xaa\x86#\xbcU>\xc8\x92\xc8\xf5\x88#B\xf6\xf1]\xb5\x0dA\x15\x1d\x8f\x91IVo\xc0\xcc\xd0\x86\xcf\xb5\xc0\x91\x14\x15\xbf\xfcGTV1nr+\xa3\xceOX\xc2S\x95%\x0b\x8b\x9b\x04\xc2\xb3\xb6\x99f\xa7OZ[\xdb_\xfd9\x9c\xfb\x11\x91P\xad\xdf\xb0\xf7 \x0f{Gl\x11n\x91\x05%\xdf#\xda\xdbh\xc0dw\xbfH\xa0\xf9=\x86\x7f \xb8y\xa9e/\xed\xaaW\xbc\x19\xb3\xb4\xb6>\x7f\xd2,\xd3\xf6\xac\xb0IP,*MV\x95\xf0\x84~\xc2\xbaK&\xe3e\x15\xa2\xc4\x8b\xbb\xfbM\x06\xec\xbd\xa3=\xf2)\x16\x8bqF\xbf\xa0S\xb6\xdf\x08\x1b\x05\xb4\"\xc9G\xd1\xebT\x9aF\x99\x8d*\xb9LX,h\x8a[\x97\xb4\xba\x93\xa7w\x8ew\xb4\xede\xf1WQE\xd9x\xda\xeb\xba\x0c?\xe1\xe8\x93{\x10^\xda\x86E\x8ex\xefh\xbb\x9di\xfd\xbb\x05\xa2\xd7\x82\x8f\x12\x84J\x94\xb3\xc3\xc0H\x8f\x07\xa5|\xf3^\xd9\xcd\x93\x8a\x85\xc9e*^\x89\xd0\xaf.\xe3u\xdaxE\x99\xe8\xeb\xcbb#\xee;\x9b\x92\xf4\xd4\x9d<]z]\\\xed\x83\xd7\x02\x81\xa8\x7fw\xdaN\xbbho\xbcchq\xb8E\x98\xa3=\x1e\xba\xe7\xe2\x134Q1\x1f\xb87\x0e\xfd\xdd\xe7W\xfc\xbd\xcc\x93l\xc3\x956\x8f\xe1\xa7\xbf\x14\xad\x12HE_\xcc\xa3\xa0\xf9qy\xff\x89\x1e\xe1\x0bY\x06R\x8e\xa4\xdb\xab\x1a\x18\xe49~l4s\xe6Vy\xf9\xad\x99`\x8a\xd7U\xdf\x9b,\xf9\x9f\xfe\xf1\xd7\xc5#_\xcau\xb4\xf9+De\xea\xea\xed\x99\xe0\xe9M\xd9\xfc\xa2~\x03h\xb3q\xaa\xeb\xb2\x87\x92\xb7#Y\xfa\xca\xe6\xf1z\xfc$;\xdb\x0c5\xcd\xaf9$\xb5\xcb z\xb2\x1d>\xff\n\xbe*j\xf5O\x9f\x8d\xf8\x8c\xf1\xdb$\x9c\xd0$O/\xaf\xc0\x0f\x15\xc3xR\xed\xbd\x83\xc2t\xfdf-}*\x9eo\xef\xc9\xa6\xf8\xd9\xcc|3\x86M;\x15x\xde\xa8\xafU\x94\x95\xb5l/.\x14\xf1~X\xc7\x8e\xafY\xe1\xbc4\x99x3&\xe6\xeb\xd7x\xae\";\xa4$\x8dKI\xf6\x925\xdbd\xda\xad\x0c\xbd\xca\xe1\xfc\xfa\x8b~w[\xca\xd4M\x19\x1f9O\xd8\xe3%4\xd2\xe1Q\xa8\x1c}\xe9\x19S^\x9e\xect\x96\x9d\xe8@\xd1\xcb\xe6\x0ew[\x9bY;-\xdd\xf6\xff\x8d\xc0\xbas;\xa2b\xbe\xcdwH-*\x05\x0c\xef\x96\x96\xc3im\xbd\xb6I\xca\x08-\xb6\x1f\x7f1e/\x95~\xf8\xa8TNN\xae.\xf2p\xb2\xdf\xf0)H$\xfb\xeb\xabW\xef\xdf~\x8f\xce\xf0\x03\x90\xb5\xc9\xc6\xa6\xed\xbcO\n(\xa0\xe99\xe8\x86,\xd9\x0d]gM6r\x1d\xea+\x84#\xbb\x07%\x83\xe0/s\xfcw\xafA\x18\x9c$\x11\xf5\x8cq\xc64\xcb\x11\x07O>\nd9}\xf7\x9d\x13+\xf0\xd1$\x8cs\xf4\x9a\xb3\xfd?\x030\xa3\x99\x14a,>\x9dy\x8b\xb9\xda\x88s<\xf0\xfe=\x86,\xf0\x8bc_*\\\xe2\x83D\xed\xbc\xdc}\xc82\x19M\xed\xb0\xcd\xccT8\x17/\x12\xed4\xe6g\xe6'\xda\xa6\x9e\x9d\xe28'\xfb}\"\x8bC\xe2\x03*\x84\\9\xbd#Y\x8f\x1f>z$\x8e\xe6\xf6\xd47c[s\x93|\"$}\xbb ym\xcc\x16\xef\xd5\xc0\xabzQx 5\xb7%\xe5\xa0o\xf9\xe5\x93$j\x86k\xd0\xcep\x12)\xf1x\xbd\xc4\xfb-:\xba\x86\xd0\x98|?\x9d\x98o\xe3\xf8f\xa7\x87gFr\xc0\x9e\xdf2\x15\x1a\x8aS\x91\xc7Z\xf7\x8c\x02\x11q}q\x88\x8a\xb5 \x85o\x80\x1d\x1f,wy\xc5O\xa1g\xca\x13\x90CF1\xd6l\x98\xe7\x9f'\x06\xedL5T3\xf5\xf23\xfb\xd1\xf0y\xaa\xa6M\x899\xda2\"s\x94\x98\xf25\x14u\x1bD\x95\x8b6\xc0\xd4-J\xec\x89U\x08\x86b\x05s\xba\xcf\x18\n\xabO)\x83\xcc\x16w\xb8R\x0d-2\xe6/5f\xdc<\xaaBQ\xcc4\x16k\x8c\x98\xea\x90\xad\x9dG\xb9 \x13\x1f)%\xdf\xbc\x0e\xe3\x7fr\x92\xcf\x9bf@\x07\x1f=\x9a\xe2BF\x99\x8b\xefCB\x00\xb1\xa9\x89\x89\x83\x87&'\x87F}\x19@\xa9&\xd3\xc8\xff\x19\x04\x84y\xd7ub\xe2\xd0\xc1\xc9\xc9C?'\xab\x1e\xea\xe5\xf1\xe7\x18S\x01\xe649+\x97\xc3\x93\xe4\xb1C\xf8\xae\xb3\xedI\xc3\xae\xf0\xa4\xd9\x1f\x8c+\xd7\xe7\x98\xebf\x05/R\xab\x06U\xea\x0d\xcc\x12\xeeC\x0b\xb0\x01Fu:\x14C\x11*\xa3}\x0c\x86T:\x1f\xba\xb6}{\xc2\xdc\xdd\xbd\x01\xe2\xb2\xb7\xd4u\xaa\xce\xd7\x17\xf8\x95\xace[!\xae\x96>\xfa?\x0b\x8b\xc4\x0f\xe5\xfd\xda\xb8\xb8\"\xc7M\n8gz\x83\xf40\\Hk\x83\xd4\x06Z\xb3:\xc4h\xe5\x02\xad\x1b~\x99\x03@\x13\xaa+\x1d\xf4#\xabN\x9d\xea\x0c\xd6fj\xbe\xe7\x18y\xb5\xee\xe5\x8bio\xc0!\x84B\xf7 \xfe\xf1\xf4\xb7\x93\xb1R'\xa95>\xda\x13\x03`\xda\xf2[!\x1a\xc2\xc4T\x18\x88`m\x1fC\x01\x9a\x9d\x0bI\x85\xd1\x9d\xc3}\xb8n\n\x8f>W\xdf\x10\xf4\x01!M}\x18U\xcbav\xf5\xb6\x014\x90\x803)!\x10\x04\xa7\x01\x0ek\x1bc\xc8\x82\x1a\xb2\xf3m\xfe?\x92\x8e \xdd\xe5d\xef\x18w\x95\xe3v\x17\xab!\xd7\x94;X\xcf\xa1\xdb\xa8}\xbd\x1d8\xedvt\x95\xeb\xd0\"\xd3\xbc#\x0ck\xc2v\x17X\x8aJ\x17\x99\xb1[\x93l\x9d\xb6[Z\xdd\x99M\xc3\x80\xa7\xf1\xc3\x16XC\x073l\xea\x96[\x0d\xc3Ta\xbcVj\x8b\xa1\x85\xda\xca\xbb\xa5\xe5\x18\x01\x8c\xd1\xac\"\xc5\x93\x17\xd1\xf2\x0bt:\x15\x82(\x9e\xea\xe0\xa6\xc8\xc1<\xbe\x08\x06cZ\xf3ve\x97\xfdQ\x9b\xc7\xeeT\x85\x9f\xa0qH\xe1\x91i{\xa0\xd2\xe9\x8a\x80Q\xe5\x9f\x93'\xc1\x93\xc3\x96\xbb\x93i\xa0\xf6P\xd8\xf6\xef\xbf\xad\xe8\xfc\xc8\x03\xaf\xe1\xedmK\xcaA\xe7I\x8a\xf5\xa4\x19\x8f\x90BF\x83\n\xa3\x15\x05=\x89\x89\xb5\x07\xe2\xd6\x07T\xe1\x85\xbd\xb6\xe0(\xe2\x0f\x9c&TS\x10\x9f?/\xef\xd8\x81A:\xd6\xb7\x1e\xac\xbb\xd0\x9eV\xa7(\xf8\xf7@w\xef\x0fF\x07a^\xe3\xa6]\x85\x8c\xb5\xe4o]*\xd3\xf199\x16\x16\xacR\xbfi\x0e\xe1\xf1_\xd4\xf2\x98\xc0\x99\xfe\xce\xcb2vM\x93\x80\xd8`P\xa7\x93\xf4f\x03\xa6\xb4\x06{Q\x06Y\xcf\x16\xab\xedH\x7f#V7v\xc57\xcc\xd2\xb0\xa0q>@\xe0\xf3\xab\x18~u\xc9\x98\xd7\x86Ax\xb0\xc3/\x83\x02\xabx\xd9\x08\xb0B\xfe\xe03\xa3\xc4\xa0\xd9\xf4\x89\x9dt\x83\xca\xc1y\x1d\x86b0\x8c\x9e\x16nG`\x04\xc1\x0c\x18\xf2\x04E\xda\x04D\xec\xd9\x8d\x1a\xe4A\x92\xd4:\x0c\xc6P\xd8\x10\x05wI\x1f\xd37\xcf\xec\x10nW\xd3\xf72ED}.(h\x95\xdc\"\x82\xf3\xe3U]\xa29I\xedh_\xeeV\xaf@\x87\x9bGZ\x100C\n\xdcp\x15\x13b\x0d\xf3\x1b:\xe3\x99L\x0c3\x8d\xa1tN*\xaaN\x0c\xbd2\xbf\xd3!\xbc3\x8c\x8d\x0dCa\x18\xb3\x97yn.\x95\xca\xdd\xc9\x8b\x7fW\xe2`\xcc\xb3\xdc}\x18\xb1QB\x1b\xccC\x8f\xaa\xc3i \xc1\xa18*\x08\x02\xc3\xef{57\x89\xb9\xec\x05O#aT\xa2\xcb\x1dB\xbd\x9f\x82\xbdU\xedo\xfei\xa70\xe7\x0d\xf3_\xcb\xf0\xd1\xf9^\nChrU}~r\xc8L\x19 1\xf2z\xff>..\xf6=\x1c%\x16G\xc1\x9a\x9bG\x8c\xa3\x0b\xeb\xfco \x99\x90\x87\x0c\x18\x8cE\xe9u\x91P\xb3\x05Ps\xd8\x98\xde\xb8\xe8\xf38\xad\xf0\x03\xfc\x05\xfeP\xa8\x9fu&;\xe6\xca*\x8c\xeb\xf9|i&\xa4\xffPb\xdb\xc8\x9b\xb0\xb2\x98h\xd2;\xb4[\x97\x80|\x18y*c\x83V\x9ah\x86\xd2\xbc\xd2(\xff\x94~\xce\x16_A\x95qU2\xb7\xbd\xff\xf4GIQ\xc73`\xae^\xcav\xfe=\xee@\xac\x0f\xdcK'\xa4\xb5\xd0\x87\xe8\xcbZ#\x084sJ\x02=\x0f\xba\xa4:sY\x05\xa9\xe8 \x14s\xda\xa5b\xc2yj\x0c\xaf\xeb\xb7\x1bS\x1f_E\xdc\x83\"\x8e\xaa\x8b\x8a@\x9e~\x82\x9f\xe7\xb9\x08>\xad86\xba\xf1#\xcey\xb1\xda\xe4\xe5[\xef\xe8c\xf2S\xef\x84\xa5\xd9\xc5\xac\x96\x90\x94\xf2\xf2#\xadSJ\x94GZ\xfb\xaey\x19vv\x12\xdd\xdfS\xf9\xd1\x8f\x1a\xe6\x89\x9dp\xb8waT\x9a\x9e\xcf\xf5\xc5/\x13,\x1f\x14\n9'Jkv%%.\x86~o\xf2[\xcc\xf3\x9f \xe8\xa1\xa7\xfc\x1c\x9c\x13\xc2R\xb1Bj\xa2\x9fS\xe8\xc8\x80*$'\xf8\xe8\x85\x81\x08\xa9p\xc3\xa7S\xa5u\x00\x0b\xe0+\xe7\x079\x18\\\xac\xed_f+\xe5\xf2\xfc\xf98\xf5\x10u\\,\xb6\xca\x14\x8f\xd3t\xe6\xe5\xf0p\x9e\xd1\x8d\xd0\x1ek\xd8\xae\x13J0h\xf3(]\x18N\x11\x84Q\xc8v\xf3\xb3W\x1f\xac\x81\xc7\xcc7\xf3\x0c\x958\xab\x836:\xdc\xd6\xdd\xa3\xcf\xe2\x0b\xb7\xf1Wc\x93\xafY_i>\xfa\xac\x8c\xdd\"\x91\xdfR\xa1\x10\xe7\xf5\x92\xe2\x81(\xd3e\x18]\xde6\xf8\xb9\xaa\x04RA%U\x976&\xb4F]\x94\xbd7@\xcc\xb3k3X\x0dh\x81?\x8c\xc1K\xef\xe0\x13\xae\x04\xde\x00\x1eQ\xa42\x99B\x08k\xbe[?\x0f.\xff\x1f\x80\xc3.K\xa1\xc8KAb\x8e\xcc\x7f6\xfd\xde\xc4\x14\x1f5\xbf\x7f\xb7k\xf2\x92e\x8e+]\xb2F\x16\x8e\xb0e\xf6WH\x04\xa9U\xf2\xab\xfb\x070O\xdd\xd7\xa7\xbe5\x85\xb4\xf8\xff\x0d\xa4\xfa\xee\xe4e3H\x87\xaeco\xc7>l\x16]0\xb62\xb1\x88c\xfd\xb9\x87\xddH\xca9\x9a{Z\x0d{sO\xf5\x04\x96!\xa5A,\xfe7\x86?\xc5\xb73\x00w\xe4\xbf\x8eA\x1c\n\xe0Fj\xda\xff\xb88\xb8B\x16\xed&8U$\x06\x11G\x85\xa1\xc2\x00\xb5\xd9\xdf\xe9$\x1b\xb5Y5\x98\x82\x18\x86\x0f\x0eF\xe2\x11L\x855n\xc7\xec\xb2\xd8\xf21\x96\x94>\x02\x0cq\xf3\xba2\xa3\xa3.\xab6\x93\x03e\x97\xe9\n\xee\x0d\xec\xbc\xda\xf5\x97\x9c+\x98\x96@/\xac\xa2\xf0\x99\xb5k\xedb{\xe0\xf7(\x8f\xc57\x07\xd0i=\x1b\xa5\xc9{l\xcd\x8d\xac\xdd\x82\xad\xe2\xce\xe6\xbf\xa6\xef\x19\xa08\xab\x03\x851g\x9d(\x03\xbb\xfc\x13\xe8%\xce\x02\xd3h/\xebEf\xb6M\xb9\xd2\x8d\xddt\x9f\x005\x0f\x1f\x14\xbd\x9f\x1a\xcc\xbcvg\xbdo\x03\xda \xea~\x01\xe0\xa9\x9bWKi\xe7\x88\xb6U\x07\xab\xdf\xd8\xa3\xdd\x96\xadw\xacRS\x82E\xecF\xed\xdfT\x1f\xac\xb2%\xaa\x0d`=\xed\x17\x18\x8b\xf8|*=1\x82\xf2*\x8e\xf9\x16\x1f\xbb\xfd\xb7S\xa7X\xf6\xac\x80\x1e\xb7\xd8^\xea\xf2\xd3w)l\x1f\x96\xc3\xd6fQ\x9dH\xe3\xfa\x8c(\x14YS\xfe\xf4\x84S\xcb\x8cK\x8f\xb7\xe61\xde\xd8\xe2\xedW]\xb5f\x99\x9f\xb7\xb07\xd7\x9a\xb3^&\x0f\xfdp\xf4@T'.\xec\xc0%3\x8d\xb3\x95\x84\xc3\x0d\x9a\x9d\xaf\xb4\xdf\xde\xf2\xbb\x11\xf95\xcfzaTf6\xd1\xeb\xa9A5\xdc\x19L\x95\xf3X\xcc\xa1\xe6\xb7\xc1|\xf1\x08L\xb8\x7f-\x9f\xe5\x96\xce\xb7\x07\xea\xc4\x1aT\x03\x16\xd7g{A)\xaa\xee\xad\xaeF\xd1\x15\x95.\"\x14h\xfc\x18\x93\xf9j\xa2\xa0A;\x10.\xf0\xe2~\xc2\xfe\xa0\x85o\xde%\xb0\xe8\x0c\xfdG#\x1a\xd1}&]\x02\x1a\xde\xd7\xbec\xdc`\x0fC\xbbhH9xnN\x86\xb7Y \xce\x12\x17l\xf0\xb2c\xde\x14\x03\xa4\\+v\\E\x9f\xa5\xab\xc6\xa71\xa6D9K\xb7X\xe1)2b\x01.\xbf\xf3\xad\x93N\xf4\x07\xda\x17\xfdW\xa2\xa7\x8e\xdcQ\xd7\xa9$\xa5/\x05\xa3\x94\x10|6t\xc3\xb0\x99\xc332\x14\xd4\x9b\xa3\xb47\xa1\xa1\x17\xa6\x00\x962\xb8\xd1\xdb\xd0\xb8yu\xfc0e\xd7\xf1\x80)\x92N\xd8uh'd\x9c\xb6\xc3\xee\x84\xf5\x81\x1f~xY\x89\xc9\x0b\x1e\x00\x90\x91\xb4>\xc4\xda#\x0cb\x88\"k3\xd3\x0e\xf0\xc2\x0c\x03\xbc\x83\xae\xcc:\x13\xa09\xbf\xba\xa2v\x13\x0f\x88\xfa\x06$\xd0\x9fC\xdd:\x14\xca)H\xb9\xcb> \xd5\xa6\x9az\xc7\xdb\x1c;e\x93d\\j\x17m\x1af\x9f\xe4\x18O\xcfa%\xf29\x9a\x91\x88\x04cK\x9bx\xd3\xd0\x0f\xdb\xa5\xc5!k\xa9%H\x81\xdeDn\x93\x10\x7f\xfc{Y\xdc\"\x93\x17{n_\xd6}\n\xdf)9\x83=\x0d_/\xfb\x1e\x87Z\xce(\xe9\xf9>\x16l\xfa\xb6\xad\xf7Y\x9e\x06\x9f\xd6V\xf7\x8b\x1b\x06gQ#\xa7\xdf\xad:Q\xc4\x01\x95\x17\xc8bw\x07\x83\xc7\xf7\xd5$\xbe\x1bzw\xb1\xf0\xd9\xae\x8b#\xbf\xbb\xe3\x7fU\x14\x98?|\xc5\xf0\xefG\x08\xd4\xce\x05\x84h\xc1\x1e\x7fz\xfc{\xf9o\xba$w\xf1\xd7\xcf\x9c\x9d\xb4\xba\x04\x1c)|Vh\x89\xda?\xbb\x8c\x0d\x14ZV\x8f7\xbe%\x9f\xfcG\xfbo/\xa3\xd7\x86\x87\xf4\xe9E\xcf\"\xb9K\xd3\xb2\x85\xa0\xec\x15\xb5\x08l\x06\xa5p76\xce\x00\x1f-z\x0d!\xc1l\x804\x17n>\x94\xbc$\\\xe1\xd7zV?sz\xfbqej\xecQ\xe7\xeb\xe9]m\x8b\x9b\x04\xe6^\xe6=^\xb5\x0d\xe4\xa7\xed\xad\xa5!\xa0\xb2\xbal\x85\xf4HB4sL\x0bi9}\xde\x1d2\xa2^\xd7\xfdK\xd05\x04\xc5OB\xfa)\xe8\xedO\x0d\xad\xe7v^~\xaa\x12\xea\xb5\xfd\xef\xdd\x80x\xa6\x93rm\\\x1eK\xda&G^\xd0\x075\x8fC\xe7\xd0\x10L\x1b\xbc}&F\xba\xf2\x94\xc0\xcb\xe2\xa8B]K\x86\x14\xa1n3\x86\x86|\xcdsGjy\x1a\xf0\x16k\xfeO\xaf\xb5\x16\xdab\xe5s\xdc\xbd\xe6aW?R6\xf0\x12\xa1\xb7\xb2\xbeJ\x90\xc2\xc7fh\xe3\xda2 \x0c\xc4\xcalBS\x1c\xa7\\=\xa2j\xd5\xd5V\x97\x1e\xca*\x94\x1f\xf4Y\xa6\x93\x14^\xa2\xa2\xc1\x99\x04\x84\xcb\xba^\x1aE)\x07\xd5\xe8*\x94\x03\\\xbd\x9f\x04\xa0\n\x03\xc2\x14\x82r\xd4r(a\xa2\x1d@\xf8\x05\x16\x08\x846n\xd4\x8c\x14\xa3?\xa5}\xdadL\xb0\xa9\x17\x1e\xa6\x81\x16\x9ag\xa2\x0eI\x1dvq\xd8Nc\xd0\xc7a\x8d\x91\xc6\xaek\x8c\xcd\xf7mL\x8c\xf6\x7fc\xc1A!\xa4\xb1hd\xb8\xa3\xb1V\xeb\xf0\xb5\xb9\xce\xf2wc\x03=\xa2\xa6\xe6\x86\x96\xe1\xe6\x16\x96\xd5s_\xd2:\x8a\xff\xd2\x97\x95\xa2sL\x1f\xcb\xed\xa3g>\x91\x9c\x971\xdc*4-%\xf0\x13&\xcb\xf50\x11\x08Ub\x16\x83)E\xdc\xac\x8d\x86*\x19b\xb8\xd4\xd6\x0651\x97\xc4\xef\x84\xe7 \xe4+\xe8+;\x98\x8e<\x85\xab\x86\x92`!q\xb0f\xcd\x1a\xceM\xf9*\xc6,[/GK+\x13\x07{\x17\x04\xc3\x12\x97\xae\x8d,>C\xe2L\x13\x81\x8c\x1b\x01\xf3\x9dR%%c\x8c\xb3\xc2\xc6\xc3~\x91\x92'EG\x8f\x86A\x89\xaeG\xba\xc2=\x87h\xc2\x12\xe4\x9f\x94\x8e\xb08\x1c:ID\xecN\x02)\xc5W\xcc\xbb\xe1AF)ucw'qh\xcdX\x1f\xc3\xa8\xb2L@a\x84\xbe~\x8c6\xccPc2L\xe3\"\xa5A\x08\x852b\xec\xc8U \x99\xc0&\x8c\x13\x80\x8b\xff\x0c\xaf9\xf6A#\xd3QLO\x07\x04\xac:\x81E\x14\x809k\xa7\xa9\x92\x91\xc6\x1af\xdeKF\x95b93t\xbaL$c\x89\xcb\xacp\xffLz\xff\xa0\xbf5\xd4d\x12\xdap\x08\xa2\xfe\xf0\xf9\xdb\xb0>$`\x9c.\xf7\xef\xab\x1d~X\xf3\x07=\xb6\x17\x00\xa1\xe3?\x84\xa0\x18N\x90\x14\xcd\xb0\x1c/\x10\x8a\xc4\x12\xa9L\xaeP\xaa\xd4\x1a\xadNo0\x9a\xcc\x16\xab\xcd\xeep\xba\xdc\x1e\xaf\xcf\x0f \x82b8AR4\xc3r\xbc J\xb2\xa2j\xbf}\xf8\x9f\xd0\x0d\xd3\xb2\x1d\xd7\xf3\x830\x8a\x934\xcb\x8b\xb2\xaa\x9b\xb6\xeb\x87q\x9a\x97u\xdb\x8f\xf3\xba\x9f\xf7\xfbA\x08FP\x0c'H\x8afX\x8e\x17DIVTM7L\xcbv\\\xcf\x0f\xc2(N\xd2,/\xca\xaan\xda\xae\x1f\xc6i^\xd6m?\xce\xeb~\xde\xef\xf7\x87\x11\x14\xc3 \x92\xa2\x19\x96\xe3\x05Q\x92\x15U\xd3\x0d\xd3\xb2\x1d\xd7\xf3\x830\x8a\x934\xcb\x8b\xb2\xaa\x9b\xb6\xeb\x87q\x9a\x97u\xdb\x8f\xf3\xba\x9f\xf7\xf7\xff\x00b$\x9c\xabtV&g\xae\xcf\x96\xed\x7f\xc1r>\xbf<\xd9y\xf3\xe5?\x8f\x92\x19\x93\x98\x8d\xfbf\xfe{\x9d\xe7\xb4\xb7\x9d\xa3\x00\x89\xb5\x11\x9b\x9e%\xee\xb5\xef\xc7\xcc~\xdfZ\xfb\xfea\xc5zW\xbe\xbf\xbc\xf7\xdc\xf5\xdd2\x9f\x1d\xb5sv\x90\xef\xc0\xcc\xf2\x1d\x90\x99\xd9eW\x1d\xab\x00\x89\xb5\x91\xe0\x02\x00\x00\x00\x00@DDDD$\"\"\"\"bffff\xd6}\x03\x90X\x1b \x0e\xd3O\x01\x840\xc6\x18cDDDDD\xac\xb5\xd6Z\x9b6W\xf208B\xd6\xe7\x10I\x1b\xa5\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x90\x13\x00\x00\x00\x83.\x01H\xac\x8d\x04W\x08\x00\x00\x00\x00\x00\x00\n\xa2\xdf\x88\x13\xc7\xd09\xa0\x00\x89u\x84*\xa5\x94R*J^}\x80\x1e\x14\xc4:M\x94\xb4$I\x92$I\xd2\x0eF\x82\x8b\x99\x99\x99\x99y\xd1\x9f\x9e\xfb\xde\xf3\xc0_W\xcd\xc6\xfd\xc1q\xb9\x8f\x97\x84 \xf6\x97j\xfb}%L\x05\x11R\x0f \x17\x966\xe3\x83\x1f\xcc\xfd\xf9\xdd\x03\x9c\xa9\xb5\x8f[\x9dR\xc0\xa5\xd4w:\xa9\xa6^\xd7\x81\xacZ\xf8\xd6X\x0d\x17+;\x9c\x08,\xf8>p\xcd\x86\xcdL\xe9=\xda\xd6\x05Wj;\xe0{s\x1d\xf8HtA#;\x0fR\x8c\xf6\x910\xa1\x87\x90\xf1Gs\x1a \x12\x89\x17\x98\x98SK\xc25\x93\x7f^27\xc6tMi\xeb\xe1\x98\xa6^n\xbd\xba\xa8\x07\xf3\x7ff\xacH\x1b\xb5FY\xe4X\xa7,\xec\xf4\x15S\xd1\x08\xfa%\xf7\xdaq2V\x9a\xeb\xe8\x87\x83\xd7\xeb\x80\x9f\xdb\x08!9\x8d0\xf3\x94!qd\x00\x98\xabw\xe2-\xe6\x8bUm\xa0l\xe8\x84O\x93\xadp\xd4\xdc\x809e\xff\xf6\xf3\x12\x7f9\xbb+\xaa\xb4\xd5\xe9uD\xe5@`K\x1e\x05\xef\xf9\x1e\xb5p\xea\xbbK\xb5\x9d\xdc\xd9\xf26X|!\x0b\xe2\xca[a\xf2\x894\xc1\xc8\x00x\xaa\xb1\xaf\xc7d\xe8\xd8\xa6n\x88.k\x85\x1d\xa6\x1a\x0ck\x8ds\x8c\x84~\x97\x84)gxah\xdf=\x9fU\xb1N]\xe4$\xc7\xa8\x8d\xb8c\x14\x112\x9f\x05\x88\xa8P\x1f>}\x80\x08\xd5\xaf\x0f\x9f%U\xf8\xff\xee\xac)M\x9c\xdf\xe4\x0c6\xd6\xb80\xfc\xae\xb7\xe2\xae\xe7\x13\x01\xfd\xca/s@\xc2l^\x1c\x9b \xba\x96>.\xaa\xf4\x06\x17 c\x0c\x84g\xf4\x0b\x903I\x895\x0eWy\xef\x00\xb7'\xab\x96Cr%\x10\x11\xfd\xaf\x8f\x12\xcc\xb7\x8b\xbb\xfa!\xad\xb9\x97\x9b}:\xbd\x02o\xe1\xe5\xae\x12\xafp\xb5c\xaf\xa9\xc69Y\xa2\xed'\x02\xddRr\x14\xc1\x89\xd8qOW\x01\"z\xe5\xea\xab\xd6\xae\x05Q\xc6{D\xa2}\x8b\x88U\xd3\x82\x94E\xce\x03\xa8\x05\xd2|;P\x18\xa1eIy-\xe3\xa5l\x8b\xbe\xf5&lO\xaf\x02~\x9e\x0d\x84\xf8\xfd)\xd9zkE\xb2\xf5\x0e\xdb|\x13.\xd5tp>2\xad\xf9\xd9k_\xc4.Z\xae\xb0\xf6b\xcd\x0fyd\x97\xa7\x9b\xb9\x8e*\xe5\xd6\xa8\x8aP\x8e\x9b \x1e\x95q9\x02\x9c\x1c\xa1\xeb\xd2\xa1\xa3\xc8\xd2V\xf8\x82.\xf5\x10m\xf6\x99\x0cXz1\x1b\xaa\xfa\x06\x81i\xee\x05\x7f\x11m\x1f\xd9\x91T\xfb\x07w\xa9\xcc\x8d\xcdRL\x91\xebBH\x18\x96\x1c/u\xe6+\x91\x06\x17\xdd\xd4\x0b\x07\xb1\xb4\x90\xd1;\x1e\xb0_\x15Sq\xc3\xe5v&\xce\xb7s\x18\xa58rL\x15\xb2\xd5P\xe9<^\xd4\x0c \xd5\x0e\xee\xbdxK#\x11\xb3\xf31\xcf\xeb_>\xa9/;`\xaav!\xc8\x12wD\x89\x98^Ax\xd7&=\xe6\xff\xd5\xd3\x86r\x89\xd5v\xf7\\e;\xa4\xd6w\xc2d\x19\xdb>*L]\xbdAS\xe2\xb2v\x0dp\x85\xdd\x83\xae1B\xaa\xd8\xa3\xefB\xea\x9f~rm\xe6o\xce\x98\xb4~Rz\x13\x91\x19'\x11^\xb9\x8f\xaf\x98\xf9\xeb\xac\x18c\xceKQF%\x11h\xffMv)\xfc\xefWT\xeaL\xec\xa2E\x8a\x9a\x0e\xd7fm\xd9\xdd\xef\xb2\xeb\xef\xf8\x89\x994\x8c\xee\xf4a\x00[u\x15\x83\xbb3k=a\x0d\xb3\xda@\xdbr\xd3u\xb9\xb2\xdd\xb9^S\xd2\xfd\x97k\x85\xed\x0b\xcef\xf6J\xf3l\xce\xb7\xcfe\xbb\xbe`\xcb`\x1dU\x02\xafF\x1a\xcc\x84\xa7\x9d2|Ht\xf4\x18o\x19\xb570\xde\x0c\xeb\xb5\xe5\xf0N\\\xd6m\"a\xd7>\x10\xa2\x9d\xa1V\xbb\x0b\xc9\x0c\x87-\x0d\x10Q\xd4\x04\x01\x11\xbaC\xc3{\xd1I\xcb1\xab\x1d6\xa8\x8b\xe1X\xae\x0d\x8e\xe6\xd9\xee\x92\x10\xe5\x7f\x88\x18\xeb\x9b\x8fz/f\x97\xcc\x8f\xc9H\xcfv\x0c\xb8R\x1a\xba`\x13S\n\x11\xc5\xcd.$\xdf\xa6\x87\xb5\xae\x9c\xbbF]|#\xbe\xba\x03\xb6P\xa5\x90\xd2\xd8\x0d\xef\xc7[\n=\x9a\x81B\x94\xd7y\x0bDx\xc1\xab\xf5\x0e\x08FA\xfa\xf5)\x83zx\xaf\x97\x80\n\xdec\xac\x1a0\xdd\xe8\x05w\xcbE\xe1\xb0\x12\xa1\xe2\xa5G\xd3\xf4\xc6\xd9\x8c\x04\xd6\xde\x03!x\x83\x9d\x18\xad\xa8\x92f\x98~*\xed\x10\x91\x9a\xfd=i@\xa0G\xccu\x03[t\xe5`h\xe9\x83M\xf8\xbb6\xb5\xa0\xf3~\xa7\xd4|\x89\xea\xe7\xdc\x87\xfb>O-\x04Y\xbe\xdd9!\xc2\xb0\xf3\xe1\xe9\xee\xc6\x10\xa6Z1N\xc6\xec\x1e\xcd\xa7\xb6\x10\x99\xf6\xe5\xff\x19HD\xcc\xf6\xfd\x19\xf5N\xb5\xad\x13(\xd4\xf4\x0dti\x9f\x97H\x1b9Q\xce\xeaf\x9f\xcd4#\x11\x7fX\x18\x9bi\xcfh\xeb\x03\x15\xde>\xa5\xa1\x1b~\x1bi\xd0\xdcO\x01v@\xa1&\xe4\xd3\xc4\xdc\xa1\x95\x97\xf3\xdc\xc0/x:\xe3/\x1a/e:\xb6\xd3\xd5\xbeRv% C@\n\x94W1se\x92\x8c\xb5\x8f\x17R6\"b\x92\x02/Y\xba\x8a{nA\x8e\xe3'\x90\x14\xda]\xde\x12:\xd9_@\xd9\x90#\x83A\xa9\x85\x03\x1e\xc6?j\xee\x11\x8e\x17=\xf6\xc9\xf5\x1fJ\xcd\xc6\xc3\xab\xe5H\x16,5\xd7\xec\xa8\xf4&\"\xc1V\xec\xb6}x\x9b=\xec8_)\xfdUr}\x17\xe7\x0ey\x88\xa5\x1eN\x94\xb6\xc0\xe2\xb8\xebz\xf7\xcd\x02\xc4\xda\xcb\xc9u\x1dC\xa3\xc2\xe9+\xe4\xab\xe81\xcf\xac?\x13N\xa6ED\x146A`\x82\x19\xbe\xd6\x96\x81\xb9\xfdG\xf0\x12iNy\xba\xe1\x83\xa1\xc2O@\x85\x9e(jq!\x08\x08L\xca\x05\xda\xde\x0d\xa8\x11\nw\xa4F\x0b4q\x17j\x1c\x9c\xd0j\xe7\xc6\x89\x99ZO+\xe7%\xcf\xf1\x97\xb2\xe9\x01r\xd4\x03)\x1dH\x08\x8c\x1a\x11\xc0\xe4\x086>\xc4\xd2\x08{3\xaa\xc1-.\xd6\xae[\xdcNC\xe5\xd0\xd7\xfa\xf2\xeeO\x14y\xf5\xbf\x8f77\x07\x1b\xab\x87\xd6*\x8b\\\xdbq\xfaq\x0f\xaa\x1f'\xe5:\x08_\xf5!\x8a\xda\x94%\xe7\xb3\n\xab\xfa\xee@vG?\xf7%S\xca\xedH\xab\xbc\xb3\xeaj\xc1\xe0\x11$p\x18\xaa\xe4\xdf\xd5\xc5\xbd\xde\x12\xe6\x93\x91C\xc0g>\xfcZW\xe1\xca\xc3\xdc\x9a\xdb\x7f\x82\x8f\x13s\xb81\x02\xea\xee\xa23&\x0e\xc1@e\xdf]\xee\xcdhc\x0f W/#\xe1\xaa\xb7\xb1\xce\xffL\xf6ctx{\xef\xed=\xebSAE@\x10EQ:\xd2{ -$$$\xa4\xf7d\xfb\xee|\xe7\xcc.\x1a @v\x130\x819\xbf\xdf%d2\xf7\xce\x9d\x99;\xe7\x7f\xce\xb9\xa7\x08xc1\xfeB\xeaD\xedJ\x88\x18\x06Q\x8c\xa1\xff\xdb\xa1\x10\x0e\xd2\xcfE\xd4\xbe\xa6V\x85\xd6N6'\x82\x83\xf5\x983\xa97\xa2\x8d\x1aT\xd9]\x90I\xa6s\x91\x92y\x9d\xef/\xc4?\x17m\x03\xb4j\xd0\xb7,?\x94s\x9cT\x7f\xd9\x95\x05\xe1Ux<\xf7\xa2\xc6\x06\x02\x0f@\xad\xf2\xfet\xb8\xba@\xab\x9a\x0c\xa3\xee\xdft\xe0>\x02\x97/\xe5\xd7$\x93L2\xc9$\x03\x88\x97\x14\xc2O\xb0:\xc6\xb1t\xde\xa7m\x0cF\xa7F\"\xce\xa8\x83\xd3#b\x7fE-\xe6\xec-@IQe\x14\x82\x0d_@\xa9\x88&`yU~U2\xc9$\x93L\xe7;\x80\x08\xc2[\xb0\x10x\x10X<6\xba+n\xe9\x99\x8c\x04\x9d\xf2\x8f?{\xa8\xdd\xda= \x0f/\xdf\x8bE;r\x81`\xfd+\x048\x9b\xe8\xf0\n\xf9u\xc9$\x93L2\x9d\xbf\x00\xd2\x0e\x1e\xcf\xddp\xb8\xf0/\x02\x8f\x7f\x0fh\x83JB\x8c\xf7v\x17`\xfe\x9e|\x98u\x1a\\\xdf3\x05\xa3\xe3\x83\xf1\xbf\x89=1\xd5\xed\xc6\xca\xddy@h\xd0\xe7\xa4\x85\xa4\xc8\xafK&\x99d\x92\xa9\xe5\x90\xe2,_\xef\xef\xa8\xb1\xa2g\xbb\x18\xdc\xdb;\x05\x15.\xe0!\xd24\xee\x9c\xbf\x19%\x16\x076\x1d\xa9\xc0\x84Yk\xf0\xf9\xde\"D\x10\xb4=:\xa8=\xb4!F\xc0\xeeL\xa6\xbe#\xe5\xd7%\x93L2\xc9t\xbe\x02\x88\xe4m%`rj4\xa2\xd4\x02>\xdf\x9d\x8f\x0f\xd7\x1c\xc0;\x17\xf7\xc4\xaak\x06a\xcb\xcd\xc3qQZ\x14n\\\xb4\x1d\x9b\xca\xac\xe8\x1bm\xc2\xa0\x94H\xc0\xea\xe0\xde\xa3\xe5\xd7%\x93L2\xc9t~\x02\x88\x16\x1eO<\x0c\x1a\xa4\x04\xeb\xa4\x03\x9fg\xe4\xa1Wz4n\xef\x16\x8f\xadE\xb5\xc8\xad\xb2\xe1\x8d\xd1\xdd\xa0\xd3(1{\xdf\x11\x98\x95@G\xb3\xde\xeb\x9d\x05\xa44\xe1\xda4\x08\xd2\xa9\xa5\xe2\xaf\xf4<\x93I&\x99d\x92\x01$@\xfd\x83\xf7\xc8 \x0cD\xdf\x01\xb5B\x80\xc3\xe5\x91\xfe\xafQ\n\x92\x17V~\x8d\x15\x0e\xb7\x08\xad\xd2;5\xb7\xf8G\x7fO\x00\xd7\x9cN\xedG\xb8=\xd9t\xa1\xfd\xd4\x0e\xc2#f\xd31v\x0d\x1e*\xbf~\x99d\x92I\xa6\xd6\x01 \x0e(\x14\x87aq \xb3\xd2\"\x1d\xb8\xb5[2v\x1d*\xc1\x13k\x0e\">\xc4\x88\xb6\xa4m\xcc\xdc\x9b\x8f \xb5\x12\x97\xa6\xc7\xa2\xcc\x05\xec\xae\xa8c\xcf->=\xd3\x8fk\x05A!,\x84\xd3\xfd-*\xea\xc6\xd3\xcfh\x8d^\x03%\x077Y\x1d \xa8\xb4\xfc\x8d\x80d%\x8d\xfb\xb6\xbc\x04d\x92I&\x99\x02\xa3\xb3k\xce\x11\xf0\x1b1\xf6\x9es\x0e\x14\xe2\xb6\xee\xc9\xb8\xbcC4\xb2.\xec\x8cg\x96\xee\xc6\x97\xdbs\xf1\xf2\xd8n\xb8\xac],F%E\xa0C\x98\x0e\xbf\x1e\xae\xc4\xba\xec\x12\xc0\xa0\x85\xa4I4\x8e\xd4t\x8d\x0d\xa8\xb1ud\xe0\xb9\xbc_\x1a\xc6\xa4F!\xc6\xa8%EDDn\xb5\x15\xf3\xf6\x17`IF>\xa0U\xdd\x05\xbd&\x96\xc0d\x9a\xbc\x14d\x92I&\x99Z2\x80\x00o!X\xff\xc0\xde\x83\xc5xf\xdd\x01\xbc}A{<:0\x15\xdd\xa3C\xf0#1\xf4\x12\xab\x03\xfdb\xccl\xe7\xc2\xf6\xd2:<\xb9j/\\u6\xc0l\\\x07Q\\\xdf8\x90\x12f\xa1\xd6\xd6Q\xa5U\xe1\xbdq\xddqe\xa7X\x18\xe9p\x0d5\x8e61 \x14\x97w\x8c\xc3\xeb\xb1\xa1xny\x06\xa7\x1a\x99J@r\x0f]\xf2My9\xc8$\x93L2\xb5\\\x00\xc9#\x06\xff\x18i\x14O\x7f\xb8z\x1f\x94\xa4\x11\xdc\xd5;\x15\xd3S\xc3q\x19\xb5j\x0fPbs!R\xa7\xc2\xb3\xeb\x0ez\xb6l\xcfU >\x8c7\xd1\xefl\xe4\xf8\xbd\xe1rO\xe5 \xc5\x17Fw\xc5\xcd\x04\x1e\x87\xadn<\xb1)\x0b\xf3\xf7\x1e\x81Z\xa9\xc4\x8d=\x93qC\xb7D<=(\x15Ev'>^\xb9\x07\xd0\xa8^\xa3\xbe\x1fS\xab\x95\x97\x84L2\xc9$S\xcb\x04\x10\x06\x83g\xa0S\xa5C\xc05\xef\x91\x86\xb1\xe8P F\xb5\x89D|\x90\x1e\xd56'r*\xeb\xc4\x07\x07\xa6\xe3\xae\x1e\x89\xc27\x19ybM\x95E\x80I\x7f-\xf5\xdb\xd2\x88\xd1o#\xed\x03\x83:'\xe0\xfaN\xf1(\xb4\x8b\xb8\xf9\x97\x1d\xf8\x85\xb4\x9b+z$K\xe3\xdf\xff\xe3V\xe4\xd29/\x0eM\xc7=\xbd\xda\xe0\xc7\x83E(,\xa9V\x10\xa8]\xee\x03\x11\x99d\x92I&\x99Z$\x800y\xc4kI\xea\xdf \xb5\xf1\xf1\xec\xc2*\xd3\x7fs\xcbh&J>\x0eT\xd5 5\x80\xfb\x97\x89\xdd\x15\xcf\x8e\xe8$\xfc\xfd\xbb\x0d \xad\xe2\xefP*\x96Q\xcf\xdf\xe1\xb5D\x15\x9e\x04\x9cz\xf1\xbe\xc7\xd8\xe4\x08\x84\xd1\x9d=\xb1%\x07\xbf\xec\xca\xc3\x82k\x86`|R\xa8\xd4\xf1\x99\xc4p<\xb6t7F\xd0\xcf\x8bS\xc20\")\x02\xb3\xf2\xcay\x9fe\xa8\x1f\x002\x9cZWj\x9cA8\x9f\xda6jkO2'(\x94\n\xc91\xc0-\x8a\xf2\x8a\x93\xe9\x9c%\xb5B\x81j\x87K\xca@\x0d\xbdF~ 2\x80\x9cQM\xe4\x15\xfa\xf7\x0b\x18\xb5S\xa9]@\xbf\x87\x11\xf3\xd7\xc2\xa8\x19\xb2x\xeb!\xc5\x87mc\xbd9\xd4^;O\xd7,\x83v7x\xe3\x82\x92\x1bX\xc3u\xd4\xaa}-\x8b\xdar\xdf\xf1\x9e\xd4\xde\xf1\xe3:?P{Af\x11\x8d\xa7\n\xbb\x13}\xa3C\xa0\n\xd1\xc3\xc5\x9e\x96aA\xf4M\xfa\xed}\xaf\xf0\xad\xef\xa8\xb39u\xb0y\x1d(\xa0\xb6\x8bZ\x06\xb5=g\xf0zm|\xdf\xfd_AVj\xa5>\xc1\xf7\x08\xbc\xde\xade\xad\x0f@\xbcTD\xed=\xa9 >\xae\xaaQ\xcd\x82\xc51\xe3\xa1\xe5\x19\xc2\xa5\xa9\x11\x9e\x8fGuR\xb4\xcf.\x86XP\x01el\xa8\x8eA\xc0Z^\xdb\x1bjeo\x18u3h\x81\xde\x0e\xde\xfb`\xe6\xeet\xc5\xa3\xb4\x06\xb9\xd56\xd4\xb8\xd9M8 qA:X\xe9\xff!\x04,Q\x04,G,\x0e\x94\xd6\xda\x90h\xf2\x063\xda\xdd\x1e\xf8\x02S\x9c\xa7^\xd6\xc2l\x02\xb0i\xa8\xb5C\x17aB\xef\xd4H\x98i\xcc2\xab\x03\xeb\x0b*!\x96\xd7u\x87I?\x8bPj\x08iRw\xfd\xd1O\xa3\x82\xa3\xac\x06\xef\xef\xc8\xc5\x17\xf1\xdd\x1b*\x91\xd0\x9b\xda ?\x9f[\xdey\xc6\x9bB\xa8]Em*\xb5\x81\xd4t\x8d\xec\xb7\xd3\x076G\x81\xc7\x9f\xe7\\\x06\x99\xfc\xfb\x98IH\xea\x12i\xc2wS\xfbc\xda7k\xe1\xaa\xa8\x05B\x8d^\xcbB\xe3\x89\xbf\x90)-\xe0v\xf6Q[Cm\xa1\xaf9\x9aq\xec\x8e\xd4\x1el!\xaf\xad\xce\x07\x96\x1b\xa8\xfd\x02\xaf\xb7\xab\xfb\xaf\x06\x10\x96\x1eb\xa9q\xc0\x07\x07\xee5\xbe\x8a\x12\x9b\xb7B\x0c\x93*\xf3+\x0c7/\xdd\xe3\xfe~\\\x17<>\xac\x03\x0e\x16T\x8a\x7f\xeb\x91\xe2\xd1\xaa\x14\xc2\x86\xc2J\xc5\xb3\xab\xf7\xa1\xa6\xd6\xda\x0d\x06\xed\xef\xa8\xb6\xb2\x99\x0bZZ\xac\xa3\x06\xb4\xf5\x0c\x8a\x0f\x15\x8eX\x9c\xc2\x94\xb61\xd8E\x80\xf2\xc4\x8a\xbd\xb8\xa8],*IB\xbar\xdeF\xc4\x98\xf4\xb8\xaac\x1c\xca\x0826\x95\xd4x\x97\xacWZ=\x19x|\x8b:\xfb4\xfe\x10n\x1d\xda\x01Wt\x8eG\x07\x92\xae\x824\x02i\x14\x1e\xe9\x1a\x1fo\xcb\xc57[\xe9V=\xea;I\x0b\xb2\x93\xa6t\xdfQ\x13\x16\x08\xc4~\xcb*\xc6\xd6\xa2*$\x93tVn=\x06\xabJ\x03x\xbe\xc5\xe7\x11_b\x01\xe1)j\x91\x01\n(\xf5%\xaf@\xfb\xca\xd4\x18fB\xd2QV\x95\x05\xc3\xe2\xcd\xf8n\xc6@L\xfdz-\xdc\x1c\xc7\xe5?\x88\x1c\xa6\x96\xf8\x17\xdfN{_\xbb\xde'\xb0\xb1e\xe1C\xf8\x17\x8fv2jI\xce:\xec\xa4\xda\xc7\xd7\xee\xa0\x96C\xedSj\xec\x95Z\xd9\x18u\xb19\x89'\xb0\x8a\x98y\x0el\xcem\xb0\xbb\xf6\xd3\xc2\xc9\"\x06\xfd\x19\x1d\x1f\xd0\xc81\xd86t\x0d\x81\x08\xe6o9\xa4\xfc`w\x81\xe7\x9f=\x93\xf1\xf4\x98\xaeB\x9a\xd9\xa0\x8c1h\x15\xf7\xf7L\xc4g\x13{\x91\xce@@YV\x8bN\x89\xe1xpT\x17\xfc~\xf5\x10,\x9c\xda[h\x1bj\x14Km\x0e(I\xab)&\x8dc\xee\xfe\x02\\5w\x03\xc6\xcdZCZ\x83\x06_O\xec\x89\xb4 5\x16\x1f.\xc3\x9a\x03\x85\xf4\x08\xa58\x93oO2\x9f\xc9p\xb8\xa6\x834\x95\xa7\xc7t\xc3;#;`P\x8c \x07HE\xffao\x11\xf2H\xea\x1a\x15\x1f\x82O&t\xc5]CI\xb0`pp{\xee=\xe6~I\x0bA\xb5\x05+\x0e\x97#\\'\xdb\x86\xfd\xa0\xaf}\x1ajd\x80\xfd=\xf2#<\xbb\xa4\xa0on\x07 e\xc3b D.\x1f\x08%\xaf\xf7\nKk\xafN\x98@\xed~j\xfb\xc1\xa1\x08@\xc49\xfc\n\xd9,\xfc\xa4\xef^\xaf9[\x1aH;IJ\xb78\xbaK\x89\x0fM:\xa9\x8c+\x9b\x87\xecU\x96Db\xa8\xd7J\x9eTJ\xc5\xf3$\x91?|\xda\xd1D\xcc\x81N\xf5=jmS\xde\xdezH\x18\x9d\x12\x892\x02\x02\xbb\xc7#)\x0bk \x1c\xbaE\x98\xf0\x001\xf4\x18\x95\x02\xb7\xf7I\xe6dW\x9e\xadeV\xcfC\xab2\xc5Y\xdbr\x14i\xb1!\xf8\xfc\xe2^\xb8\xbc}\x14\xbaF\x05\xe3\xf7\x9c\x12hUJ\x8c!\xad$E\xa7\xc0\xb6J;\x1e]\xba\x9b+ \x02z\xc3\x1a\x9a\xd7\xe6\x93(\xd4/p\xd5\xc4\xa9\x03\xda\xe2\xc1>I(w\x88xi]&\xde\xdd\x94\x8d\x10\x8d\x02\xb5.\x0f\x1e\x1a\xdc\x0ew\xf7J\xc13C\xd3\xb1\xa3\xac\x06+w\x92\x00e6\xfc\x9bz\x8f\xa9\xa7Y!\xa7\xc6\nA\xdeGo,\xb1*=^~\x0c\xad\x8b\x84\xa3 BZ\xf9\xf083f\xcf\x18\x80i_\xaf\x83\x87A$\xd4\xe0\xaf&\xd2\x12o\xefnx\xcd\xa9,$~v\x0e\xbfJ\x16\xda>\xa7\xd6\xd7w\xcfg\x0c@\x12i\xc5lA\xa5\xc5(\x18\xb4\xb8\xf3\x82\x8e\x18L\x1aA,I\xf5\x0c \xfb\xca\xeb\xf0MF>~\xdfw\x84=3\xfe\x0f:\xb5\x99\x16\xd1\x1d\x8d0e}M:\xf1\x14%\xadF'\x01\x87\x07G-M\x90\xbc\x99\nI\xf2\x7fi@\x1b\xb1\x8a\xce\xfc:\xa3\xc03w_\xa1\xf0[n\xa9\xcaF\xd7#\xa0Bny-\xae\xa4\xeb\xffk`\xba\x14\x9cxg\x8fDi\x8c|\x8b\x0b_\xee+\xc1\xa3+\xf6\"\xa7\xa0\xd2\xab^\x8b\xe2\x95'Uc\x1d\xee\x0eJ\xd2\x86\xae\xeb\x14\x0f\xd6\x1d^\xdc\x98\x85\xd7\x96g\xe0\xf1\xd1]1,%\x02s\xe8\xde\x1e\xfbi;\xdd\x96\x12\xf7\xd35n\xe8\x92\x80\x95\xfb\x0bY\x0b\x19E\xf3\x08\x85w\x83N\xdaL?DZH\xa5\xc3)\xa9\xfa.\x8f\x8c$\xa7\xa0\x17e\xf0h\xdd\\V\xe9\x03\x91\x0b\xe2B%\x10\x99\xfe\xf5Z\x02\x91\x80\xccY-\x91B}f\x9e\xe1>\x13\xd7\xb9L\xbc\x9f\xab\xf4Y\x97\xce\x00\x80py\xda*\x8b1*<\x08\x9f\x92\xc4?6\xc9,]\xad\x98=\xf9\xd4$\x82\xc7\x87\xe0\xb2\xf6\xb1xn\xed\x01\xbc\xb5j/\x9f\x7f;\xd4\xca\xa5\xa4e|w\x9a\x91\xeb\x98\xe9\xf2\xc6\x9c\x93\x80\xc0\xacU\xa1\xd8b\xa7\xc5)H\xdeTI&=\x9e\xdc\x94\xe3\x99\xb5\xe5\x10\xf6\x97T\xab%M\xc2\xa8\x03\xc2\x8c\x1b!\x08\xdbh\x91\xde\xbczo\x01V\xe7U`hr\x04\x12\x83u\x12\xd3\xdeO\x8bx\xdb\xa1Ri\xcf\x84\x16\xb3\x95\xc0c\xbc\xcf\xee\xd7\x10\xf5\x82\xdd\x894\xea\xdf>,\x08\xbb\xab\xecxcs\x16\xee\xb8\xa0\x13\x9e\x1a\x98\x8a=\xd5\x0e\xbc7\xb2#\xf2\xacN<\xb7\xfe \xae\xee\x18\x8f\x8et^\x18=\x8b\xf2\xb2\x1a\x81\x00\x937\xcb\xd6\x1c\x1d\xccN\xda\x8a\x8c\x1b\xa7%v\x8f~P~\x0c\xe7\x889\x8b@dD|(\xbe\xbd|\xa0\x04\"\"{g\x99\x8d\x81xg\xb5D\xba\x8eZgj\x17\xe2\xdc\x0eB\xe6}H\x0e\xa1\xf8\xea\x84w\xdc\xc4\x81/\x83\xcd\xd9E\xa5S\xe3\xbd =1\x9e\xc0#\xa3\xd2\x8e\xab\x17\xedD\xefO\x96c\xf0\xa7\xab\xf1\xfe\xae\x02\x18\xd4\x02^\x1a\xde\x0e\x97\xf4N\x05\x9b\x83HFy\xbf\x11c/\x83Ac-.\xaa\xc2\xab$\xf53\xdf\xd5\x13\xa0\xb41\x1b\xd0/\xd2\x88\x05\x99Ex\xea\x87\xad\xca\xfd\xf9\xe5J\x18\xb5V\x84\x9bfA\xab\x1aG\xa7\xf5#P\xb8\x85p\xe6B\x02\x88\xdfy\x13{UF\x1ef\xae\xcd\xc4\xb7\xc4\xe4\xb7\x1d,f\x97[ \xc40\x97\xfe\xd6\x05\x7f\xbay6D&\xeeo\xd6(\xa58\x0e\xd6z<\x0e7\xd2B\xf4\xc8\xb1\xb8QL\xbfs\xc2\xc7! \xa1\xb08\xe9w\xab\x0bF:/D\xad<*e\x1d\xe3-\xc4\x9a\x87 \xc8\x8c\xe54$\xa7\x949\xd7\xccY%5\xb8\x90Ad\xc6@\x08\xbc\x1fXI\x9a\x88Bq\xae\xdc&\x9bx\xd8\x83)\xe8\x1c\x7f\x9d\x9f5t\x8fM}\x8b7\x83\x98\xe8\xd4n\xc9\x98\x98\x1cJ\x12\xb9\x1d3\x16l\xc6\xec\x8c|LJ\x8fA3\xd4\xcf\xc7\x00\x90(\x0e!mg\x08\x81\xc5\xbf`6\xbc)5\x93\xee.(\x15]\xe9o\xec\x12\x9au\x9a9\x14\xb19,\xaf\xce\x81R\xd22\xc2\x08(\xa7uN@(\xcd)D\xabD\xd7(\x13\x0ctc\x1fm\xcbAr\xb0\x1e\xa9\xc1\x1a\xe9\xbc\"\xde\x07RI\x8f\xf6\x18/\x06\x87\x9b5\x10\x112\x86\x9c\x94\xb8^\xcb\x88f\x1c/M~\xa4-\x04DH\x13\x19I\x82\xd67\x97\x0f8\x17A\xa4\xa3OB?\x97\x89Y\xf8\x03\xcdi\xc2\xd2\x107\xec\xc1L|dB\x98\xb4?\xf0\x95>\xfc{\x13^\xee:\x020\xcb\x91\xe2j\xc3\xda#\x15\x18\xdf&\x12\xcf\x0dm/\xb9\xe1\xde\xb34\x03A\xa4Q,\xcf)Cfy\x0d\xe6O\x1f\x00#}\x0f\x1b\x8b*a)\xaba\xd7]\xce\xdf\xb8\xbb\xde\xbd \x88>\x1c\x8e\xd6\x95]\x83NJ\x97\x06\xd0\x87\xfd\xf3\xffGm+5\x9b\x8fg\xf1rL\xa1\x96+?\xd2\x96\xa5\x89\x8c\"^\xf15\x81\xc8\xe5\xdf\xac\xf5\x82\x88\xd9\x80s\xc4\xae\xcb\xf1Fs\x03\\\xc3\xad\x858\xf8\xf1\x89\xe6\x02\x103\xdc\xa2 \x1a5BI2\xe7@\x8f\xa5\xb9e\x98\xd8!\x0e\xed\x08'\x8d\xe47b\xb4\x83\xa3\x83\x10\xc7\xa9\xd9\xbd\x0b\xe6\xf4\xae\x99\x82p;\xa7E\x18\x9d\x12\xe1I6\xa8\x15\xf7\x1e(\xf4\xc0\xe1R \xd2\xc4\x11\x94\xcf\xd38\xef\x9c\xe1\x07VD\x1a\xcc\nT[\xc7=\xbf>\x13\xc3i\xf1+\xb9\x08\x16i\x12\xec\xef\x9eYP\x85\xa4P\x03\xbe\xbfl\x80\x94*e_\xad\x13\xefo\xce\xf6~2\na&D\xd8\xff\x18\xc9\xe3\x91bGB\xe8y\xb1)L\xa6\x06i\xa0\xdf\xef\xc7[\x18\xec\x80\xfc\xe8Z\x07\x88\xec$Md4 \x91__6\x103\xbe]G b9\x97@\xe4\x12x\xf7\x0b\xde?\x03c\xb35c\x96\x9f}\xe8\xc1Jr<\xbb!'\xa1\xe9\xb15\x1c\xdf\xc7\xf1\"\x9b\x9a\x03@,\xb4*\x9cp{\xb4\xecm\xc5\x03\xb1\xe7\xd5\x9e\xd2\x1a/\xba\x10x\xf0\x9e\xc5v\xd2H,v'RB\xf4R\xa8\xb7\x857\xaf\xbd6\x9c\xd3sQ\xb7g\x02\x9b\xb0\xc6$G\n\xe5NQ\\]P\xa9\x807M\xc9?q\xf2\xb8\x8d\xe6ehnO\x1f\xb6;\xb5\x0b\x0b\x12\xf5j\xa5\xc2E\x93o\xcb\xa01\xa5\x8f\x94\xf7'\xca\xa0\x92\"qxC\xfd\xd6E\xdb\x91u\xb8\xdc\xbbI(\x8a\xc7 5\xab\xeb\xa9!\x068EY\xff8\x05\xb5\xf5\xf3\xfc\x07d\xf0h] \xc2\x9b\x80;I\x13\x19C 2sz\x7f\\5{=<\xbc/\xca\x16\x85\xa6\x81\x08\x7fo\xd9\xa79G\xe7\xd3N9\xf0+\x9eZ\x1c\xbc\x9b\xe0]\x80f\xb3,s\xdc\x12\xa7bi\xee`_\x0ef\xbc\xa3 \xfd\xd5>\xe6\xcfIc\xefi\xc28\x83\x9b\x0b@j\xa1R\x1cB\x95\xa5KFy\xad\xa4P<\xd4\xbf\xad\x94\xc2\xe0\x9a\xef\xb7\xe2\x91\x0b:J\xdeRW\xff\xb4\x1d]\xa3C01-\x12\xd95Nla\x80\xe1M\xe6\xfa\xe6\x9dc\x89m\xe0\x13Hz\xbf\x00\x16\x87\xde\x1ci\xf2\\\x9c\x1a)\xfc\x98]*\x16\x17W\xb3g\x13\x9b)\x16\x9eb^\xc3\xe0\x8d\xbfH\xf7-\x18NI\xb1\x9a\xda<\x1cu\xa9m\x1c\x85\xd3b_\x8c\xd2\x9a\xa0n\x1d\xe3=\xbfL\xee\x81e\x855\x9eg\x97e\x08\xc3\xd2\xa2\x85\xa1\x89\xe10iT8P^\x87\x1d\xc5Uxwk\x0e\x0eqRF\x02J\x08\xe2t\x9a\x7f\xd1\x1f_M\xad\x1d!\x91\xc1\x92\x19\x8f=\xc9d:)\x85\xf9q.#\xf1/\xf2#k\xa5 B|`|J8>$A\xec\xe6y\x1b\xd9E\xf1(_\x08\x94\xd8\xf9\xa2*\xc0\xbe\x9c\x9bj\x14\xd8)\xc8\xfb\xb3\xa9\xf4 \xb5\x8b\x9b\xf9\xd155\x02\x99\xe5\xf7\xb5\xbe\xf6\x11\xb5E>\xcd\xc4_j\xd7\\&,H\x8c\\\xa9\xe82sw\x1e\xae\xed\x9c\x88\x89m\xc2\xf0\xfe\xc5\xbdp\xf7\xfcMH%\xd0\xb8\xbaS\x02\xa6\xb7\x8b\xc1\xf5]\x12\x11\xa6\x12\xf0\x9f\x83E8\x94[*\xa5\xf6 Zp\xdcXq\xa4\xe3~\x00\x87k\"3\\\xc9]\xa9\xda\x82\xc1\xdd\x12\xc5\x18\xad\x02\xf3\x0f\x16\x8a\xecR\x0b\xa3\xf6[\x92\xee-\x0dJ\xaf\\\xa2\xd6\xe9\xba\x887\xf6\xffHt\xc8\xb9\xae4\xaa\xeb\xa9\xdfK\xb4z\x9f\xa3\xe3\x8dKB\xa8\x10~Cy]Ph\x8c\xd9\xbdpJo\xc1&Bq\xc7/;\xc4\xbd\xbb\xf3\x84%\xd9%0\x85\x1a\x11B\x00Rju\xc0\xc6\xfe\xed|\xadP\x03\xcf\xeb\x86c]\x94\x05.\xa3\x8bk\x87v@\x87p#id5\x92\x8f\xbcL'\xe7/~\x98\xafJ\xe4G\xd6\x9a5\x91Z\\\xd5>\n\xf3\xba%\xe2\xa7\xb5\x99$\x83\x06{S\xff\x04F\xe9\xf5%c?\x895\x97\xff\xfa\x1a\x0b\xa0O\xa2i\xce\x1c\x13\xe0M\xde\xb9\xb5\x85\xbe\x02N\x189\xc8\xa7\xbdk\xfd\xec\x1b\xdd\x9c\x00\xf2:\x81\xc1C\x87\x0e\x97\xe1\x81e\xbb\xf1\xc9\xf8\xee\xb8\xadK,\xba\xc6\x8cDa\x8d\x15\x9cN\xe4U\xd2D\x18\x00~\xca\xab\xc2\xf3+\xf6x=/\x14\x8aOi\xa1\x14\x1d\xf3\xf2\x15\xc2ZTY\xc3Y\n\x19\xdb# }\xa2\xcdP\xd2b\x1a\x98\x10\xa68T\xeb\xc4OY\xc5\xde\xd8\x0d\x01\xdd\x89A\xb3\x17W\xfd\x1cR\xfdhA.'\xc0\xd1C\xad\xc2\x05\x04X]\"L\xd0\x92\x06TB\x12\xffr\x02\xad\xdc\xbc\xf2p\x02\x91W\xa1U\xf7\"U\xf9\xaaS\xdc\x13\x07F\xbe\x8e\x1a[\x0fhU\xe2\xac)\xbd\x91hP)F\xcf\xdf&\xee\xcd,\x12|\x05\xae\xb2jj\xac\xa95\x0cNJ%\xab\xdfYt\xfd\x054\xaf7P?\xa6D\xd2>l\x08\x89\x0b\xc5\xb5\x9d\xe2q\x98Tu\x85\x0c\x1e\xa7\xd3*\x1aK\xac\x89\xcaQ5\xad\x18D\x18+\n\xea\\\xb8\x95\x84\xcf\x9fv\xe7C\x12\x105\x7fu~W\xac\x847\xae\xe3_hZ6\xe6\x97\xa8\x8dn\xc1\xaf\x80\xf3\x8d\xbdL\xedQ?\xfb\x19\x9b\x13@\x8ai%\xdc\x0c\x93\xfe\xbf\x0b\xb6\x1e\xc2\x0c\x87\x0b\xf7\xf5KC\xaf83\x12\x0cZ\x1c\xaa\xb6\xd2\x02\xb1\xe3\xeb\xbd\xe5xly\x06j T\x10b(&\x06~\xe71\xb69\x85\xb0\x02\x95\x96\xf0\x98\xf0 \xbc5\xb6\x1b\x86%\x86#R#H\xd9\xef\xb2*lB\x91\xcd\x89W\x86w\x12\x1e\\\xba\x0buU\xd6\xee\x08\xd1\xffJc\xf4\xf4\xf5\x8f\xa4\xfe\xabPQ\xa7I\x8e1\xe3\x95\x91\x9d1\x90\x98|\x84N!\xdd\\\x1daNN\xb5\x0d\x1fn\xcb\xc1\xbbk\xf6\xb3\x9d\xf5o\xd0i\x8e\xd0\xea=1XM\x10^\x82\xc7\xf3w\xd2<\xb4py\xf0\xd2\xf4\xfe\x9e\xb1\xf1!\xca\xbf\xaf9\x88\xdf6g R\x14\xad\x80\xe9\xf4\xcfw\x04D\xdd}\xcf\x8f\xa7\x99q\xd2\xcf\x84\xe6~\x0d\x01Z\x9aY\x8fm\xadO\xfbP\xf9TV\x96\xee\x0c\xf5\x8e\xb3\x1d\x8e\x1d\x19\xf2\xd0\xbc\x99\x81\xdd\x90\xe9\xfc\x01\x11\xfa\x14\xf2j\xad\x18\x18\x1b\x8aK\xe8\x1b\x99\xb7\xe1`K\x00\x90\xa3\xc4\xd9\x10hB\x98\x1d`\xffQ>\xd3Xv\x0b~\x05\xdf\x04\x00 \x8a\xe6\x04\x10\x96\x01?\x82J\x19C \xf2\xf4o\xbb\xf2\xf0\x1bI\xfb\x03\xc3M\x98\xd4%A\xbc\xb3{\xa2\xe7\xc6\xc5\xbb=\xb3W\xecQ#X\xcf\xe0\x91C\x0c|$\xeagF\x15\xf08I\xe9\xb1\x9c;\xeb\xabK\xfbb@\x8c \x15v\x0f\xbe\xc9,\x85\x85\x98x\x9f\xe8\x10\x84\xeb\xd4\xb8\x8e4\x9b\x08\xa3\x16W~\xb7\x1en\xab\x93\xb5\x03N!\xf0)\xad\xc2\x0fHs\xd1\xc4E\x85`\xf6\xd4~\xe8\x1c\xaeG\xa5C\xc4/9\x15(&\xe9\xbf7\x81I\x9b`\x1d^\x1c\xd1\x1eZZ\x9c\xafq\xfe+\xb5\xea\x01\x02\x9d\xef|*\xaf\xc2\x07b\x1f\x13\xb3\xbf\x82m\xb1\xa9\xa4JO\xeb\xd5\xc6\xf3@\xb7x\xc5\x93\x1b\x0e\xe1\xed_v\x90\x96\xa1\xe7t$\x8f\x12\xf0\x1c5Om?\xad\x88E\xd7\x0f\x8e5\xe3\xda\xce\xf1\x12\x88\x9da\xed\x83=$:\xc0\x9b\xf9\xf8T\x929\x1b\x9a\xebN\xa1^\xf3\xf3 \x90\x94\xb6\xe6\x05\x10\xe9S\x15\x9f!\xee\xb8\x8d$\xf4\xc7\xe0p\xf5[K\xda\x88\xa0\xd7\x08\x0f\xf5J\x12\xcbl\x0e'I\x15j\x04\xe9Xk\xe0\xe0\xbd\x9ac\xb4\x0f\x0f\xee\x81\xc3\x8d\xbbG\xa6c0\x81G\xa1\xc5\x8d\xe7IS\xf8p\xd5^\xbc0\xa5\x0f\xac.7\x96\x10(\x8dN\x8e\x90*\x08^\xd77\x0d\x1f\xaf\xc8\xe08\x92\xcb\xa4\x85\xee\xf6\\\xca\xfb\x0f\x8f\x0f\xef\x80\xae\x04\x1ey\xb5N<\xbdz\x1f\xbe!\x95X\xa7V@\xa7R\xe2\xe5Q]0&%\x12\xffG\xda\xd1\xca\xfcrl\xda\x9d\xc7\x9eR\x9c@\xf1\xb0\xc4\xcc\x04AC\xc0\x11\xc3\xfb%\x0f\x8e\xe8\x88\x9bz\xa4@\xa7\x10\x14\xb9\x16\x17j\x9c.\x91\x83 %\xff]Q\\\xed\x97\x92n%\xedch\x02\xda\x86\x9c\x15\xed\x83\x9f\xed{\x8d\xd6\x1c\x8f\xb3e\xfa\x88\xbd\xdb\xee\xf6IN\x8dc\x00@'_\xbb\xde\xa7\x89\xb1\xda\xff\xc5I\xce7\xf8\x807\xb41\xd2\xcdi\x88\xbdh\x0e\x9d\x86\x11\xa6\xfa@\xa4\xb9h\x81\xef\x9e\xfd\xd1\xe0\x9a\x02`\x13\xe1\xcd\xfe\xdaXz\xe58\x86ERO@ \xffn\x81w?\xc0_b\xc0\x1c\xe6\xa7-\xeb\x05\xfa.fI\xae\xedl\xa2n9\x1a\xc8Q\xe2\x9cW\x17\xc1\xbb\xc1\xee/]\xd9\xc2\x01\xc4\xed\x13t\xfc\x01\x90\xc2@?\xd8\xd3\xd1Bb\xb0\xfd\xa1V\xbe\xce\xa6\x1e\x9dW\x8aPF\x19\xb4:i\x83Y\x14\x97\x1d\x07\x1eL\xfd`w\x9a\x82\xa2\x82q\x11\x01\x84\x93d\xb5\x0f\xb6\xe7\xe0\xc3u\x99x\xfb\x92\xbe\xb8\x86\xeb\x9a\xd3\xc2\xbao\xc9n\xfc\x9c]\"\xa9\xbc\x93\xdbD\x82\x93\x1b\xc2\xe9f&w\x1f,v\xb4M\n\xc7\x05 \xe1\xa8s\x02\xcfR\xdf\xffm\xce\xc6\x9bc\xbb\xe2\xa7+\x06\xa2#iC\xd7\xcc\xdb\xc4\x91\xec\x08W\xd3*h\x17\xebu\x17\xb4;\x95\xb4`S\xa8%\x11\xe8\xc5pP\xd3\xe5\xbdR\xf0\xfc\xe0\xb6\xa4\x88\xb8$\xf3[N\x8d\x0dO\x0cl\x8bk\x87\xb4\x97\xb4 \xbf\xd4=\x9awH\x1ci\x1f\x1d\xe3\x91{v\xf6>\xfc\xd9?8\xbe8\x0e\x9b\x03\xb9,\xefk~\x80GC\xc4@\xc2A}?\xa0\xe1\xd4\x0e\x82\x0f<\x14'i\xfe\x92\xe2\x14M\x87\xe6/W\x90\xef\xc7\xb9\xcd\x01\\\xfe\xe6W:\xbe~\xc3O\xd4\x1e \xe0\xba\xff\x81\xff\x15\x01o\xf2\x1b<\x80\xc5\xd4\xfeOM\xfc\xe1\x07\xde\xe3d\x0fEe\x8b4\xf1^\x87\xc0\nJ\xc5\xf9\xa9A\x9emR\xe3X\xd3tchO\xf3k \xc7\xd2z\xe6\xf4V\x97Gdx\xd3\xab\x14\n\x9foMC>\xfe\xed8 b\xba\xd9\x88\x18\xa3\x16\x956\xb7\x04 \xd3\xfb\xa6\xe2\xae\x1e \xf8\xbd\xa8\x16\x83\xe2B\xd1/!\x0c\x1f\xed<\x8c\x9b\xbb%\"\xde\xa4Cl\x88\x11y\x85\x15\x11\x04V\xe3Yj\xe9\x16\x16\x84H\xbd\x1a\x99\x95\x16|\xb6+\x0f\x0f\x8f\xee\x8a\x9b\xbb\xc4!\xb3\xc6\x81\x8f&\xf6\xc2\x92C%\xb0\xb9\xdd\xd8Vn\xc1`\x1ao\xd6u\xc3|\xde\x1eB}-\n\xa9\x04|\xdb\xca\xac\xa8%\x00a\x86/\x95h\xb7\xbb\x85 \xa4\xbd|\xbe%\x9b\xd5\xebNRB\xab\xd3\x99%xl\x9a\xd7?\xe9>8fd[q\x8d\xaf\xdb\x19%\x97\x1f\xe7\xda\x8f\x93r\x174\xf3\\.\xf6i\x1a\xecw^q\x9cY\xa9\xea\x14\x1aHs\x92\x03\xcd_\x0f\xc4}\x86\xce=\x95\x19\xae\xa9\xe7?\xe73G\xf6\xf1s,\x8ee\x18\xda\xc8s#\x02\xd0XX\xf2\x9d\x12\xacV\xe2`U\x1dV\xe7\x97{\xeb\xa8\xb7L\xb7\x08\x9e\xeb\xab\x0cv\x01\xf4e\xb3\xe7\xc6\x16\n I\x01\x00\xc8\x923\xa5\x81\x1c\xa5j\x06\x10\x8b\xd3\xcd\xae\xafB\xa8V\xed\x92<\xaf\xc4\x93\xd7\x1cg\xe1\xbc>WV\xf9x\xadV\xa9D\x94\xc6\x9b}\xd7Y/\xc8H\xf0~*\x1b\xab\xf7\xe4\xe3\xee\x9e\xc9\x04(\xc0\x91Z\x1b\x8eT\xd7\xb1\xad\x94\x03\x04W\xf1\xfe\xc4\x81*+*\xe8b\xedI\x83\x18H\xda\xca\x83\xbf\xee\xc4\x81J+\xda\x87\x1b\xf1\xde\xa6l\xf4\xfax9\xcalN\xf4\x8f1aKQ5\xfa\xffg)\xfa\x7f\xb1\x1a\xfd\xbfZ\xe3m_\xfe\x8e\xfe\xef\xfe\x8a\x0fI{\xe9\x1f\x1d\x04\xb5\xb4\xdd\x01)\xf1a\x8cQ\x85\xd5\x85\x95R0 ]+\xbbQR-\xdf/\x81\xd1\x9b\x1b\x0fboY\x1d\"\x0d\x9a\x96&X\xf1^\x85 \xa7\xcbE\xd6t\xe2\xfc@\xff\x96\xf9\xf7_NlN\xbb9\x80~\\\xc25\xa6\x11\xe6\x9d\xe1~\x8e\xcb\xfb\n?\xb1\\\xc9\x02\xda\x02\xc9E\xdfsf\xc4\xd9\xe6#\xe67\xbf\x05\xd0\xaf'Z\xe6\x9d1?\xbe\xcf\xcf>O\x1d\x7f\xa0\xf9nL\x10\xc6\x12\x97\\\x85*k?N?\xd21IZ\xed\xa7 \xe6V\x9f6r\xfe\x03\xebNL\xf29\xb8\xdc\xe3%\x8f\x08\x97\xcfZ\xa3\xa25\xc2I\x0cUJ.\xc2\xc4\x11\x9a\x99\xc7\xf5\xfb'j\xac\x8a\xae)\x91\x989\xa97\xad(\x01y5V)\xf2zbj4V\xf7O\xc3\x17\xbf\xef\xe78\x90\xa7\x8f\x03\x10o\xd2A\x93\xee\xa6\xca\x8a\xba\xb0+\xe6l\xc4;\x17u\xc3\x90\xf80LO\x8f\xc4\x15\xd4xg\xb8\xcc!\xe2\xbb}\xc5\xb8\xfb\x97\x1dp\xda\x9c\x9coj/\x89\xf4\x1f\xfb\xfa\xdf\x88`\xc3\xd6\x0d\xfb\nq\xdd\x0f[\xf02i m\xcd:<\xdc/E\xfa3\xf7\xaf\xa2._d\x14\xe2\xef\\C\x84oI\xab\xfa\x8d\xfa\x1f\xbb\xe9\xe7\x11\x87\xc0\xa8\xfd\x86\x80n\xd2\x12b\xfaK\x0e\x14!B?\xc8\xf3\xc6\x90\xb6\xcab\x9b\x0b\xb3\xd8u8<\xe8}z>\x19>\xe0 \xf3\xbd\x10N\xa7Q\xde\xe0c7jaa-dw\x1e^\x1c\xd2N\x8a\xccoe\x81\x84\xcd\xb5\x85s\xad\x0f@x3r\x91O\x03j\x88\xfa\xa2\xf1\xa9\x15\xf8\x83:\xd5\xe6\xa4\x94\xbbS\xc6\x8cc\x88\xbd g\x9cF\xabh\x88>\xf0I\xdf\xf5=\xcb\xae\xa06\xd6\xcfq\x9e\x83/\xdd\x08o)\xda=n,\xcb+\xf3\xa2I\xeb\xc8)\xc0\xf9\xfb\xd83\xce\xdf\xe2QI\xcdp\xedXj\x0f\x05\xd0O\xef\xe3U\xed\xe1\x8d\xeb\n\xa4\xf0\xd5p\x9c$ \xf2O\x00\x110\x19\x1c\x0c\xc69\xfa\xb5*\xf4L\x8b&i\xde y\"\x1d\xa8\xa8\xc3\xce\xdc2vM\xbd\x94@`\x02\xbdp\xce\xf5\xb2\xa4\x1e\x08\\\xcc\x0b\xe0\xaa\xce \x1e\xa3J\xa18\xeau$\xf2.\x99\xdb\x83\xab;\xc4\xe3kb\xcaN\xa7;\x85$\x7fv\xaf\xac\x1f\x8cb\xa3\x8b\x0cG\xa8q]^I\xb5q\xca\xec\xf5\xb8\xa4c\x9f\xce\xbf\xa0^\xffm\xb4\x1a\xef@\xb0\xfe\xbd\xc5t\x8d\xed\xa4\x12\xcf\xe8\x94\x80N\xe1F\xe8\x94J\x14[\xedX\x99S\x86\x1f2\xf2\xbc\x8b4X\xb7\x8f\xfaOn\xe0Y\xd8\xa4\xe3*\xc5p\xc4\x98\x9fG\xa5e\xe0\x0d\xf37{:_?\xcc=sT\x07\xe5\x01\x1aw\xd3\xee\xc3\x9c\xafg\x11\xdd\xd86\x02\xd9\xaet\xbe\x89\xaeM7\xab\xdc\x0bo\xf0\xd5\x9b\xa8\xefz\xe9\xd3B\xbe\xdcy\x187\xd0\x9c\"\xf4\x1a\xe9~Z0\x84\xac\x827 \x90]zs}\xf8\xab\xf4}\x00\xbc\xf8\xae\xf3IS\xfe\x12'm\xeb\xec\xfb\x00OU\xeb\xfc\x10\xb5\xe4F\x8e\xc9\x91\xf0C!\x93\xbf\xc4\x9a\xfb\xb7\xf0?\xaea.\xfeL\xb7\x1f\xdc\x909\xa3\x11\xcc\xf7\x0f\x97\xe20\xbd\x1a\xfb\xcb\xeb\xb0!\xbf\xc2k\xbej\x1d\xc4\x02\x10\x9b\xce{\xf9\xd9/\xa6\x19\xae\xcd\x1a\xc3\xf3g\xf9~9-\xd3\xf4S jG\x01\xa4\x171\xd7\xef97\x7f\xc7\xe4\x08<6\xb8\x1d\x06\x91\x16\x10gPJ<7\xaf\xce\x85\xd5$)<\xb1r\x1f\x0e\x1d\xa9\xd0\x12\xb3\xff\x8d\x98#\x9b\xa3\xdaH\x0c\xc1\xe5\xe9\x0e\xbbS\xb4\xb9<\x1e\x9b[T\x1cuYeWX\xbb\xcb\x0d\xab\xd3\x05\xa7[<\x9a(\x8d\x0b\xae\xcc\xcf\x0ei\x8f2\xab\xb3%\x96\xb5e\x0d\xea\xfaS\xd8x9\xa5\x03\xc7\xf1p\x90\xe0\xbb\xf0\x16\x96\xf1\x97\x06\xe3\xe4\x19\x98\xff\x14c\x1aO\xe7L9\xbb\xbf\x80\xfe\x06o\x9e&\x7f\xcc\x89\x03\xa8]\x03o\x9c\xcfW~\x9a\xc1\x98&\xd6\x97\xab\xd8|\xf5\xd9\xae|8*j\xbd\xe5\x0fZ\x0f\xe5\x04\x00 a\xadl}\x94\xf9x\xf4\xc38M,\x92\xca\xc7\xe9\xe7\x81\xa4\x81\x1e\xa9Q\x98}i_\xb45\xaa\x90iq\xe3\xd3]G\x88\x07+0\x92\x8e_\xd3>\x9a\xb4\x023\xa6\xcf\xdd\x88}\xac\x8d\xe85_r\x96YI\xac\xa7\xc5\x90\x14\x17*\x84hU*\xc2\x10\xc9L\xc3\xde\x15\xcc\x0e\xb4\x04\x02\xa1z\x8dh\xd2\xa9\xc5\x9a#\x15\nD\x98\xbe\x82B\xc1%h\x9f\xfe\xc3l\xe6\xddo\xe1\n\x87\xb9\xa4\xa1\xac!\x80\xe2=\x95\x02p\xf5W\x9d&\x8a\xfe\xdd(I\xc6\x1eq\xe5)\x8c-t\xc3\xe2\"b\xd87\xd2U\xc7\xd0\xb9\xe94F\x0d\xfd\x9e\xe1\xe3\xd8\x07\xe8\x18\x9b\xde8:\x94\x139n\xc0\x89\x81\x8dG\xc9E\xe7\x8e@X\xd0\xbe\x9cC%\xca\x8b\xe7ou/\xbf\xa4\xa7\xf8\xc1\xb8\xee\xf8\xbf\x9f\xb7\x8b\xfd\xdbD \xa3R\"a&M\xad\x82\x00j{q\xb5T\xd6\xb6\xac\xa4&\x96\x80g\x11\xcdw<\xcdg\xd1\x1fV \x02\x9aY{\x0bpS\xd7D\x984J\xd49[T\xca\xa7jj\xbdq\xea\xa8\xee?\x0c}\xf0\x16\xcca\x8d\xc2\xdft\xd5]\x1aq\x8e?\x00\"o\xc8\x07N.\x9f \xb7\xcc\xcf~,@\xa4\x06\xf0\xee\xef\xaao\x02Q)\x05T\xd3w\xf3Cv\xf1\x89>\xfc-\x9f\x02 \x105\xb4\xb2\xb5\xc1\xdeVo7\xe6d\x06\x90)\x04\x04I\xba\x10=^\x1a\xd5E\x02\x8f\x1fs+q\xd7\xcf\xdbQN\x00\xc1f(\xaem\xfe\xdc\xc8\xce\x98\x94\x12\x86\x97\xe8\xe7\xe4\x99k\xc4 \x8dJ\xe8\x97\x1a\x89>\x04*\x83\x13\xc2\xa4R\xb5$\x92\x88\xb9UV.,%\x18\xd4JIq\xc8\xaa\xb2\x88\xe9aA\xe2\xda+\x07\xe3\xd6\x9f\xb7\xbb\x7f\xdf\x9d\xa7$m\xe0\xdf$\xc5\xb3\xd6\xe3\x80\xd3u\x19,\x0eo\xdau&\xa5B$\x95\xf60\x01\xc9\x01\xba\xf8\xe3\xf0\xaf,)\x07\xad\xbd\"5I\x0b\x12Ri\x81\xde\x0c\x8f\xe7BR\x83.\"m&DZ\xac\xbc\xa9\xaf\xd3\x94\x90\x0c\xfb)\xcd\xe1I\xd4\xcf\xcd\xf5'\xed\xa7s\xa7\x10\x98\xcdZ\xb1\xed\x90\xfe\n\x83\xd6\xf5\xca\xb0\x0e\xca//\x1f\x80\x08\x8d\x1a1:\x05j\xe9\xfeBh\xbc+\xdaFbZ\xfbX\xdc\xb2h;\xb6\x1e\xa4\x8f\"\xd4\xf8\x13=\n\xf6<*\x91>\x0c\x83\x06\xd5e5XF\xc0{E\xc7x\xd4U\xb5(\xd3\xfc\xa5\x8d\x04\x8f\xfat=\xfcO\xa5\x9e*\xf3\xed\x16E\xcb\xe1\xdd\xdb\xf0G\x9bd;\xfc\x13~^g\x99Ok\xfd\x83\"I\xa0\xdaZR\x8d=\xa4\x99\xb3\x86\xde\xcar*\x97\x07\xd0\xa75\xa9XJ\x9f\xe6\xc1\x0e\x17\x9f\xe14\xa9p\x18@.g\x06>\xa1[\x12\x86\xc5\x9a\xb0\xa5\xdc\x8ai\x0b6#\xd5@*\xe6\xe5\x03\xc1\x1a\xc5\x8d?l\xc1\xddKv\xa3\xdd\xb4~H!0\xf9\xea\xb2\x01bWR;\xbb\x86Iu=\xc4}\xd5\x0e,\xd8[ \xae \x06\xb9\xab\xa8J\x91\x1e\x1d\"\xb9\xcd\xe6T[\xb1`W\x9e\xd0%\xd6\xec\xf9zJOa\xf5\x8c~\x8a\xfbV\x86\xba_[\xbdO\x89\n\xcb\x14\x89\xc9kT\xe8G\xcc7\x85\x93-2'\xab\xb2\n\x1brJ\x92`\xb1_\x8b\x10\xfde\xd2\x8d\xfc!\xcd\xfbE\x1di\xfc\xb9\xa8\xb6v`$\x8b\x8d5#\xd5l\x90\xd4g\xde\xd3))\xac\x8c$ y\x90\xc0l\x1a\xfd\x9d\xf7t\xf66\xa0\xd5\xcc\xa7s~\"\x10\x9a\xfaKv\xb1\xea\xe1\xfe\xa9R@b.\xdd\xd7\x1dK\x0ebW^9\xdaG\x06\xe3\xfeA\xe9\x18\x11c\xc2\xff&\xf5\xc6\x84o\xd6!\x97?\x8c`\xfd3t\xb1[}\x1a\x1e8\xe2\x9e]\x16\xafS\xb4(\xcb\x0b\xd7\x8a\x0f$\x16\x84S\xe9/\xf4S\x12\x8d\x95yv\x8b\xa3\xdb}\xef0\xe1\x0c\x8d\xcf\x8e\x0c\x97\x1c\xa3\xc2\xd2\xf7\x17\xa6Sc\x15\xef}\xb0 \xc5\x1e\x91\xad\x0b@\x02\xf1\x86\xd2\xb6\xa2\xfbc\x11;\xc6\xd7x\xf3\x9c3\xa7\xdf\x0f\xaf\x17n\x03\x00\"\x8ai\x9c\xfd\xb2\x07\xd7\xcf\xa0\x03\xefl9$\xbd\xcf_\xae\x1a\x0c\x97\xd3\x0d\xde\xba\x98s\xd9\x00\x14\xd5\xda$\xd3\x0b\xff\xde?:X\xb1\xb3\xb4\xd6\xf3\xc9\xae\\\xcf\xe6\xc2*\x81\x18\xa3\xb2\x92]\xf1\x88I\xf2\xbe\x03\xc7e\xcc\x96\x8a9\x89\x92\xa5:\xbb\xb0R\xd9\xaf\xbc\xce\xf5\xee\x84\x1e\xc2\xab\xc3\xd2\x15\x03\x12\xc2\xdc\xb7\xfe\xb0Y0\x1bu\x8a\x97FtBo\xd2b\xc2\xf5^kZ\x99\xd5\x85\xcd\x85\x95xb\xd5>d\xe4\x94\xeaa6p>\x9f\xa3\xb9\x9a\x1aK)\xc4\xf4w\xa3\xa2N\x88\xa4\xfbzdP;IK\x8a0xS%\x14Y\xecX\x96S\x8ag\xd7\xecGm\xa5%\x95\xae\xb1\x8eVv\x1a\x8e\xdf[\xe1\x17\xef\xf6\xf4f\x8d\xe5\xbe>mh\xe1k$@\xe5<_\xbc\xa7\xd3\x85\xc0csq\x15&\x11h\xcc\x9d\xda\x0fc\x12Bpw\xff4<@\x00LZ\xcf54\x87{\xc1\xd9.\xf9\x81*\x958XY\x87*\x87S\xca\xcb\xe8n\x195\xa0\x9bR\xbby\x9e\x9f\x00\x12\x8a\xd6f\xac8?\x88\xddj\xb7\x9c\xa1\xb1\xd9\xe3\xeb\x98*\x81\x1c\xa4[C|b)W\xefT*Z\xe3j\x08\xc4|\xd0\x9a\xebX\xf7\xf1i\xab\\\xfe\xe2\xe5\x864\x10-\xa7\x1aa\x8f%\xa6\xec\x1a\x0b\xda\x84\x18\x10\xaa\x16\xb0\x99\xb4\x11\xe6smIr?BRwFY-.I\x8b\xc4[\xdbr\xf1\xf8\xc2\xad\xde\xfe\x0c\x14Z5\x9bi\nI\x1deu\x95\x93mu%`jO\xfc\"\x87\xfe\x9eM\xff\xbf}wN\xa9z\xc4\xe7\xab\xc4gFv\xf6<\xdc;I\x119c\x90\xb4x\xd2C\x0d\xa8\xa3\x05\xb5\xa5\xa4V\xda]k\x1f\x16\x84q\xa9\x11\xe8\xee\xdbo\xd9\xcevR\xb3\xf1;\xfa[\xe3\xebe+\x04v\x08\x10\xb8>\xc8\xb7S\xfb\xa2K\xb8\x01Nz\x85\xc5\x16\xa7\x94\xa6\x84+\x03v\x8d4\xa2_|\x18f\xd05J*\xebB`\xd2\xcf\xa2k\x8c9\xe1\xe1\xd9])!\x04B#\x92\"\x08@]xgk\x0ez\x93\x86\xf5\xc5\xf8\xee\x12;\xe4\xdb\xef\xf9\xc9J\xfc}\xe9nl\xbcj \x06\xd35\xb9|mU\xa5E\x07\x9d\x9a7\xdbV\x1d\xc5uN\x93\xe2$\x00jA\xc6\xfb\xdf\x9a\xd0w\x9b\x9f\xe7\xb3\xe7\x8e\x1e\xb2kmK#\xfe\x90\x9fE`I\x17OE_\xc3\xeb\xb9u\x0cE\x1b5XWP\x89\x9d\x0c Fmk|^\x81@\xde\xb9\xb0\xe6_\xf2 \x81\x0f\x1f\xc3j\x89\xb3U\xb0\xa7S\x89\xcd\x9bl\xf2\xe2\xd4h\xec\xa5\x97\xfbSv\x19\x06\xc6\x9804\xd6\x84\xc5$\xadO\xfa\xdf*Ir\x08Q lf\xe2d\x81\n\x84\x1a\x0b\x10bx\x9c\x18\xe5\x08\xe2\xccl\xe3\xe6\x0dj\xde\x1c\xbf\x8c~\xefN\x9cr\x121e.\xe0\xde\x03\x11A\x1bE\xb7[x\xe4\xfbM\x8aK~\xdc!\xb6\x0d1\x08\xb1\xbc7`w\xe1\x95M\xd9\x982s\x0d&\xccZ+\xc5z\xe4T\xdb\x11kP\xe1\x85\x0b;C\xcd\xdeWv'k\x07\x8d\xad30\x92\x98~w\x85^\x8d\xd7\xc7vC\x970\x03\n\xeb\\x|\xd5~\x8c\xa0{\xe0\xf6\xca\x86,\xd2t\xdc\x18D\xf7\xf6\xfc\xa8.^\x14p\xb9\xd9+\xa5\xfbqc\xc5sR\xc48Z\xe81\xb4\xf0+h\xaeoo\xce\xc6AR\xbd\xad\x84H\xbbJj\xc0\xd9\xde\xef\x1b\xd0VJ\xe4\xb8\xbb\xcc*\xa5-\x89e\xb7D\xefFy\xec\xb1\xd2\x97\xa2%U$d\x93]Q\x13\xfas*|\x7f2\x94\xeaZ\x99*\x7f>\x11\xc7\xe8d4\xe3xl\xe2\xfc\xdb \x9c\x97X\xaf\x99\x84\xcd\x1f9uI5g\x93h\x95q\x9e\x81\xecg\xd4\x9d#\xeb\x84\x93I^\x7f\xac\x06\"`\x1dq\xb5\xe1\xbf\xe6\x96\xe1\x9f\xbd\xdb\xe0\x9a\x8e \xe0\xbd\x8c\xcb\xbe^\x8b\xbf\xf5H\x86\x9b\xde\xfa\xd7\xdbrp)\xfd\xed\xca\x8eq\xc8\xb6\xb8\xb1\xeaH\xc5\xd1hp\xae\xda\xf5f#.\x9cA\xaaL?\x04\xe9\x96\xc1\xe6\xbc\xe0P\xb5U\xb0\xb9<\xb0\xb9=\xbc\xe1\x8eT\xd2x\xee\xe9\x97\x8aPb\xbc\xff\\\xbc\x03\xa5$\xe9\x7f1\xae\x07\xfaF\x07cL\xfbX\xfc\xb8)\x8b\xf7JxS\xa71{!W\xa1\xce\x86\xb1\xbdS1<>T*N\xf5\xd0\xaa\xbd\x98M\x8c\xff\x8e\x01\xe9\xb0\x11 <\xf3\xdbn\x94\xda\x9cxrP;)\x8d|\xbf\xf4Xl\xe0b6!z\x06\xc0\xfa\x85\xa2\xa4<^\x16\x9a'\xcf\xd7\xac!\x85K)Hy\xb5\x12\xf4\n\x14YTR\xe5\xc4\xfd\x15u\x120\x84\xe9T\xb0\xd3\xb9\x16)u\x8b\x10\xa8\xbd\xf4l\xd1\xbe&\xf6/\xf7\x01P\xa2\x1f\x92\x9bl\xbej\xd9\xa6\xac\xccf\x1akJCf\x1b\xadJ\x81#\xb5v\xac\xe0\xfd\x0f\x8d\xba)\xf5\xcf\xffJ\xd2\x07\xd0\xa7\xaa\x19\xae\xcb\xdf\xda\x93\x01\xf65\xf8\x80/E\x12\xe6\xfdwC\xaeO\\\\\x8b\xc3\x14\n\x8e\x9a\xb0>%\xc6\xfe\xaf\xad\x07\n\xf1\xf1\xee<<\xd23\x11\xef\x92T\xde\xcel\xc0\x9c=G$\x97\xdcGH\x13\xb8\xabW\x1b\x84\xd3\xd9/o\xce\xc5\x81\xec\x12\x0e\xc8\xe3\xfe\xfe\x95{t{\xca9\xb6\x83\xa3\xd3\x93\x82Tt\xbd\x12\xec*\xad\x91\n=\x89t\x9dH\x9d\x02\xf1f#.\x9b\xb3\x01K \xc4\xaen\x1f\x85^\x11&\xfc\xe8\xcd\xe6\xdb\xbeQ\xb6\x1f\x11]\xd8\xb6: :\x84\xb4%\x90\xb4S\x8a\xd9\xdbs\xf1\xf1\xd4~\xb8\xa1\x83\xb7\x86R\xbb\xc8`<\xb4d\x97\xa4m\x8dI2cPL\x086\xec\x96*\xb3v=n\xb4\x9d\x1cTy\xb8\xac\x8e4\x8c:LJ\x0e\xc3m\xdd\x93\xf1\xde\x8a=\xe8H\xcf\xe7\x82\xa4p\xbc\xbb#\x1f\xef\xd0\xefw\x0d\xed\x80v&\x0d\x16\xe4T \xaf\xa2\xeeha\x9cc\xa4:\x06!\x06\xe4\x16\xa2\x83\xe47\xb1\xbf\xbb\x85\x03\xa4L\xfe\x11\xc7\xfa\xf0\x9e\xddkM\x1c\xe7ux\x9d3N\xa0h\x12\x10\x97\x1d.\xf3:\x99\x184\xad\xf59\x05\x12\x14X\xda\x0c\xd7\xe5\"p\x1f4\xd3=\xb0\xa5\x85\x93k\xde\x19`\x7f\xae\x173\xf1(\x80\xec#\x86\xfb9T\x8ak\x9f \xa6\x1aI\x8c\xef\xaa\xce\xb1xeh:\x1e\x1e\x9c\xee\xad\x00D\xfc\xbb\x86\x84\x85\xd7\xb7\xe5\xe1\xc5\xe5{\xa4Hu(\x14/\x93\x04q\xc4\xcf\x0b'\xf1~\x8b\x96\x18\x0e\x08\xb0\xff~\x1f\x085\xa8~\x1a\xe9\x9b\\A\x00\"\xa5I\n7\xb5V\x0d$9\x80>\xf9\xcdp\xdd\xe64\xff\xb2\x95\x85cs\xb8r(\xa7\xb5\x89\xf7\xb3?;\xcf\xb4\xe3\xf7\xed\xf5)\x15\xc5\xeba\xd4nw;\xdc\xb8u\xc1\x16\xdc\xb4h'>\xdfW\x8cm\x85\xd5\xd8B\xed\xd3\xbdE\xb8n\xe1v\xdc\xfb\xe3V_z\x0e\xcdj\xfa\xf9\xa0\xdf\xd3\x16\x84\x12\xdeS\xe0\x9cP\x9c\xcbdBj\xa4\x14m\xfe\xc2\xda\x03H3k\xd16T\x87\xc7I\x9a\xb7\xd8\x9d\x18\x99\x14!\x9dSt\xb4\xd4%\xf7m\xdc5\xaa\xf9\xfcJ\x87K\xe2n\xc3\x12\xc3PUm\xc1W{\xf2\xd13\xc2\xc0\xc9\x1d\xf1\xd6\xd6C\xa8\xb3:00.T\x12\xa1+9\xef<\x9b\x9d\x84\x06|\xbc9N$H\x87o7g\xe3\xad\xed\xf9\x88\xd5*\xf0\xe6\x98N\x98;\xbd?n'\xadl\xde\xb4~x}T'\xc4\xf0q\xfa\xfb7\x9b\xb3\xbcQ\xf3\xde,\xb4G'%=\xb7\xce\xe1A0\xd0\xfd\xba[\xc6wS\xdb\x0cc\xc8\x1b\xe2\xe7\x1e\x8d\xf5i#\x81\xac\xa7\xfe'\xfb#\x83\x07k\xf1?\xb1S\x8c\xb6\xd5\x9a\xaf\x98:\x05\xd0'\xbb\x85\xde\xcbzx\xd3\xd3\x04Rm\xf1\x8e\xa3\x1a\x88\x97Mz\xc4\x010\xe9\xbe\x86\xdd5y\xd6\xfa\x83\x98\xb5\xe30\x82LzpI\xa4\xbaj+\xc0R3\xfd\x0e\x8dr\x16\x9d{e\x80\x13^\x03\xa50\x8e7\xe5\xffA\xcc\xb7]h\x10\xde\x1c\xdd\x15\xf7\xfc\xb4\x0d\xbbI\xade\x8f\xaf\xdd\xc5\xd5x{|\x0f\xa9\xb6\xc7\x91:\x17~\xe1T\xcf*\xc9C\xac~\x14\xfa\x10\x9f\x1a\xc6\x9b\xd4\\\xa3\x97=\x82\x8e\xd6+_M\x03\xf5_\x9e_\x81\xbb\x1c\xc9\x18\x18\x1b\x8a\xbbH;xh\xeeFl*\xa8\xc2\x87c:\xa3\x92\x00\xea\xfa\x1e\xc9\x12C\xe7\x1a\xec\xcb\xf3}.\x85\xc0\xe6\x06\xe6\xfc-\xa9A\xd7\xc2\xe9\x1e\x7f\xff\xcf\xdbQJ\x9a\xd1\x15\x9d\xe31&9\x14\x93\xa91\xc8\x1d\xa8\xb0afF\x1e^X\xb5\x0f\xbe\xf0\xfbE4\x87?\x8b\xec\xb8\x08\xa0\x8cz\xf4\x8b1\xa3\xdc\xeeh)&\xac\xe60?\xc9\xe9D\xce=b\xcd\x94\xed\xdb\xfe\xa6 \xe7e\xcd\x89\xfa*\x1b\\(\xbe\xec\x14\x0ew\xab\xde\x06k\x07\xff\xe3\x99\\>\xcd\xac\xa5\x12;\xc3p\xe4\xf9\xb3~\xf6\xe3}\xae\x7f\xd4w\x83\xe0d\x82S\xa0V^\x8aP\xe3\x8d$\x91\x0f\xa9\xad\xb5\x06K\x7f\xe1\xe2Mz\x0d\x07\x92|J\xe7,l\xc2d?#\xe9\xfc\xe9\x8c\xacbi\xbf\xe5\xd1\xbe\xc9\xb8\xbc},\x12L:|\xb9=\x97V\xa0\x88\xa7/\xec\x8c\xc1\xb1f\x04\x91\x90\xf2\xca\x96\xc3\xd8\xcf\x12K\xb0\x81\xa5\x1bN\xa3\xc0AI\xcf\x10\xc8u\x92\x00M\xf4\xa6K\x916\xf4\xb5\xaa\xbd\xf4\xff\x87i\x88\xe7\xe8\x1aw\xad\xda{D\xbb\x90\x18\xfd\x95\xed\xa2\xf0`\xdf4DhT\xf89\xb7\x0c[\x8bk\xf0\x18\x01\n/\xe8\x10\x8d\x80\xcf\xf7\x14`\xe7\xc1\xa2\xa3Z\xc3\x17\x0d\xce\x9a\x03\x0d\x83\xb4K`u\\\xf8\xc2\x92\xdd\xf8b\xef\x11)\xc5<\x07DU\xd0<\xd6\x17T\"\x8f\xdd\x12\xf5jN[\xb2\x94\xce\x1f_O#\x02\x08tzt\x8c\x97\xca\xf3\x1e\xae\xb1\xb6\x94\x85\xa3\x94ye\x8b\xa7\xbf\"~\xe0~\x04\x96\xee\x9f7i9\xddy\x83N\x15\xec\xc1\xc9uz\xa6\xb5\x8b\xc1G+\xf6\xd0\xf7\xa6m\x8d.\x15#\x03\xe8\xc3Rey\x0b\xbf\xaf\xb7\xe0\xdd\xa0\xf7'\xbf\x19\x9b\xf2\xd2\x1a\xf2\xa3\x9b+5\xa5\"\x94Z\xb4o\x11\x1fi&\x93G\x1e\x14\x8a\xd7\xa0V\xdd\xfb\xf4\xd2\xdd\x08'\xa6~51\xf9\x8bS\xc20!%\xec\x0f1\xa6\x860\xfb\xdd\xad$\xd1K\xfb-j\x16_\x9e\xa0?\xdc\x07\x87\xeb\x15\xd4\xd8\xa0!\xcd\xa1O\x9bH\x84\x12\x03gmbSa\x15\xec\xa55\x1d\x08\x04\xe6\x12\x90\xff\xc8/\xa9 \x9b\x9bWoM\xf0\x9e\x90\xd9PA`\xf1&\x9dwl\xd5.6\x8d)\x95\xb8\xbdk\x12a\xb3B\x92\xc2\x14\x82\x9c\xc6I\xa6FQ\xd0Y\xbe\x1e\xbb\xe2\xbf\xdc\x84\xfe\x1c\xd1\xce\xc1\xa9\xb77\xa4\x9e0\x88\\\x98\x14\x81\x8fXX\xe3\x04\xa7\xcaV\xa7\xc0^\x1d@\x9f\xcd\xad\xe0\xbe\x98\xb7o\xc2\x9f\xd9\x96\x1bK=O\xe5\x88]\xe1k\xcdK\xa2x\x1f\x8c\x9a\x01\xa8\xb5\x0f\xfa\xc7\xc2-X\x9a[\x8a\x8b\xd3\xa2\x11O\x8b\x8a\x05\x92\xfcZ\x1b\x16d\x16\xe2\xc7\x9d\x87\xbd\x0b\xcc\xa8\xfd\x0c\x1c\xc0bu\xe1\xfb~\x9b\x83\xe6\xf9\xf8\xc01\xdf\x94\x9d\xb4\x8eH\xb3\x06#\x13\xc2\x90IB\xa2\xf4Q\xb4\x9e\xcd\xf4\x17\x03\xec\xf7K+\xb9\xbf@\\\x8d\xc3\x9bC\x87\x9c@\x9f\xc9\n\xb8\xdc\x19\xa8\xb5\xcdF\x95\xf5}\xe9\xa7\xcb\xbd\x87\x8es\x1a\x8f\xc9'\x01\x91+H\x1d\x98@\x080\x1bZU\x81\x83\xa4\x13n\xc4\xd9\x8f\xc0l\xfc\x96\xfe6\x9e\xcey\x84\x16\xd9\x13\xa8\xb1\xaa\xc7vK\xc6\xbf\xfa\xa7\x92\xc6!\xe2\xb7\x9cr\x8c\x9f\xb9\x06c\xbfZ#\xfd\\|\xa8\x0c\x16:~\x7f\xdf6\x18\xdf#\x99\xf7\x1c\xf4\xd4o:\xf5\x9f\x06\x9d\xfa\x9ft\x8d=n\xbb\x139\xc5U\xd8\xbb'\x1f\xdf\x1f(\xf4\\\xdb!JHM\x8e\x10i\xae<\x9b~gF1\xb4\xa1\x7f\x878\x8co\x13%k\x1f\xe7\x1f\xf1\x9e@S]/#\xcf\xd2\\\xd9\xb3\xe8\xc9f\x1c\x8fk\xa5\x1f_\xf3G\xf2\x94\xe7\xcc\x13\xc3\x08@`\xd4y\xbd+[\x07q\xf0\xdd%\x01\xf4c!:\xf7\\^\xe3M\x03\x10\x85\xf0:I\xd9\x0bQ^7LRA\x92\"\xa4\xcc\xba\xfcS\xa2\xf2\xba!\xf4\xf7\xef\x89\x99\xbfu\x92\x118Q\xe2eP(R\xa1Qy\x1b\xff\x9f3\x04{\xa3\xce#Hl\x9f\xc6\x15\xcb\xae\xef\x1c\x0f-\xcdvSQ\x15\xa6\xce\xdb(%4|ph{\x04k\xd4\x986w#\xd6\x17V\xb2\xb0\x8f\xeb;%x7\xc4I\xbb\xf1}\x80oH\x1f\x88F\xd5\x99T\xe6\x9f\xe9\xa7\xf03\xa9\xcf\xacz\x8dN\x0c\xf7H\xb6X!\xe0\x80\x9aS\x99\xea$ \xeb\x96.\x89\x08\xd2(\xa5\x08u\x99\xce+\nB\xd3\xf70\x12\xcf\xd2\\\xe7\x9f\x811\xb9\x92\xdd\xa5\xc7\x1f,\xb28\xd0+:\x04)\xd1\xc1\\\xe1\xb4\xb5\xbc\xcby\x01\xf6\xfb\xaa\x15\xad\xd7\xe8\x00\xfa8\x02\x07\x10Ax\x99\xd4\x81\x7f\xf0\"\x98\xd43\x05s\xa7\xf6\xc5\xfcK\xfax\xdb\x94>\x98{i?L\xa4\xe3\xd2\"q8\xef\xa6\xf3_=\xc5h\xac\x06d\xfbZ\xfdU\xd5\x9b+\n\xc6\x85\x9b\xd0\xd6l\x94x\xfd\xfd+\xf6 \xc2\xa8\xc5\xbak\x06\xe1\xe6n\x89Xy\xd5\x00\xb4\x8d\x08\xc2\xa3\xab\xf7\xf3\x16 \xd2C\x8dH\x8a0y+\x11\x1ek\xd3\xcb\x80\x88\xa7\xb8\xb8\xd3\xba\x82JeV\x9dK\x18\x97\x1a-\xc0\xa8\xe1\x0d\xbdA\xa8W1\xady\x0c\x18^\xf5|uA\xa5o\xe3\\\xe6\xa8\xe7\x00\xf9\xf3\xbd\xa8\x03\xfc(\xebS\x97\xb3pOl\x9ai{\x86\xc6\xe6\x84\x8a\xc1\xc7\x98\xb1H\x90\xe2\xd2\xce\x17\xa7F\x1d\x8d\xbdj\xe9\xc4%\x9eS\x02\xec\xfbI+Z\xdb\x81Xa*\x03\x05\x90\x81\xf4\xf2\xef\x87\xd5\x89\xdb\x87\xb4\xc7\x17\x93z\xe0\x92\x94p\xb8H\xe8\xdeYX%\x19>/i\x13\x86/\xe9\xf8m\xf4w_\xc1\xa8{\xe1\xff&\x8d\x91\x83C8\x07\x95\x9e4\x8ej\x87\x07\x95\xa4\x02\x8fj\x13\x89Z\xba\xc8\xe6\xa2ji\xfd\x0d%\x8d'\xa7\xda\x82Z\xa77\xd5:\x9f/\xd5O?Q\x02\\\x07\xad\xfa\x80\xa5\xbc\x16\xdfg\x16y&$\x9ba6\x1b\xdd\xe0\xdc<.\xf7\x02b\xfa\x9c\xe3\xa5\xf9\xeaV\xe8\xd4\xf8tK\xb64O\xc9I@\xce\x04\xd5\xda\xc9_\x919\xbd \xd7\x8aB`Ak\xfe\x10\xe7Dz\xf0\x0c\x8e\xcf :\xf7x3V\xb9\xcd\x81q)\x91P\x98\x0d\x90\xa4\xbe\x96K\xec\x0c0\xb9 ZKq+Y\xd7l\xa2k\x17@\xbf\xc2\xc0\x00D\x10\x9eC\xb5\x15\xc3\xbb$\xe0\xf9\xe1\xed\xa5M\xed\xd7\xb6\xe6a\xe8\xe7+q\xc5\xf7\x9b\xa4\x9f/o9\x0c\x81\x8e\xbf@\x7f\x1f\xd6\x854q\x0eF\x14\xa4X\x0e\x7f\xe8w\xae\xc5\x91_g\x93T\xdf*\xd2*\x9e\x1f\xda\x1e7\xd2xUN7\xba\x93\x1a\x9c]\xeb\xc4\x97;\x0ecxB8B4\n)\xaa<\x9fS%x\x83\x0fO,?\xa9\x14\xf6\x82@\xe8\xd3]\x87\x05\x0e\\|\xbc\x7f[a\x18\xef\x9b\xf0/\xb5\xb6\xb1\xb4\xc2\xd9\x9d\xcd|\x9ayqr2\xce\x93\x7f\x01\xbc\xe5`u\x0d\x9e\xc5.\xc8\x95\x16|\xb8\xf30\xc2\xf5j)(S\xa6VM\xfe&\xc5\x1b\xd4\x84kM\xc0\x99\x0f\xd4\xfc>\x80\xfb\xdf\xe5g\x1f\x8e\x9d\xb8\xa5\xfe\x81R\x12<;\x85\x05\xa1gl\xa87\xadI\xcb#\x06V.y=\xbd c<\xda\x8a\xd6\xf5\x7f\x03\xec\xb7'\x90\x05\x1aI\xd2\xfa\x05\x1c4wc\xd7D\x84\xd0\x08\x1f\xef\xcc\xc7}?n\xc1\xb8\xb4(\xbc5\xae;&\xa7\xc7\xe2A\x02\x92g\xd7gI\x7f\xbf\xad[\x927\xc8\xce\xe5\xe1\xbd\x92\xc6\xe7]\x11\x84\xfb\x18\x08\xaarJ\xf1{~\xb9h\"\xcdbtr\x84\xc4\xeb'\x7f\xb7\x1eS\xbe\xdd\x80\x9e\x1f-CZ\x88\x1eO\x0eJ\x97\xf6@\xb6\x95T\xa3\xac\xb8\x9a\x997\xab \xc7\x17\xca\xe9C\x9a\xd08\x8e\xdb\xe8\x1b\x13\xa2\xc8\xaau*&\xb7\x8dV|=c \xbe\xbd\xb4/\x8c\\\x9f\xa0\xbc6\x0e^\xb7\\\xae\x8f\xd0\xe6\x04\x93\x82@\x0f[\x14\xb3`snD\x9d\x9d\xb3\x0bo\xa2 e\xd1qN0\xd6\xf1\x98\xb3Y\xe50\xe91?#\x0f\xeb\x0b\xaa\x10o\x92\xb5\x90VN\xfeJ\x94\xd3\x9ap\xad{\xcf\xf0\xbdp\xcdk\x7f\xf7X\xfe\xe1\x13\x98\xfc\xa5\x0f\xa9\xc5\x1d\xfd\x85\x8b\xa9\xf1\xb7<\x827\xd3=bs\x99\xb1\x8e4\xc3\x18\x0c\xf8\x1f\xc3\x1b\xbb\xd1\xb7 \xe3\xb0\xf6\x91\xd1J\xd6\xf4\xc7>a\xd8_\xe2\x88\xe8\xcd\x81\x00HO\x96\xe0\xa3\xc3M\xe8\x12\x1e\x84|\x9b\x1bO\xad\xdd\x8fI$\xc5\x7f1\xae+\x06\xc5\x87\xe2\xbfc;\xe1oC\xda\xe3\xdb}Gp\xd8\xeaB\xc7p#GhK\xd28qPN;2\x8b\xda\xad\xc71\xdctxm\xbe*ia+\x84\x95$\x9d<\x80j\x8bxa\xcf\x14\xf7(\x02\x0e\x93N)\x05#qU\xc0\xee\x91\xc1\xc4\xbb]\x98\xd1)\x1e_M\xe9#\x95\xc4-\xb2\xba\xf1\x16\xe7\xa2\x92\x82\xf7\x14\xf3\x1a\x90\x18\xefB\xb5M5\xb8c<^\x1c\xda\x01U6'\xf2kl8TQ\x87Ii\x11R\xfd\x10\xadN#\xa2\xac6\x894\xa6gh\x9cLZ\xdc,\xa5\x8d\xa5\x9f\x9c\x07\x7f'\xaa\xac7\xa1\xd6\x1em\xa2\xeb%\xc7\x9a\x11\xcc\xbe\xec\x16{,\x1d\xbfYZ4\xc2\xb1\xd2\x16\x9b\xb1D\xba\xef\x0fv\xe4J\x1b\xfe\xb2#V\xab\xa6\xd7\xe5x\xff\x0c\xdfG ^E\xf5=\xaa\xde\xa5v\x9d\x9f\x92+k.\x0f\xc1\x9b\x92\x08eV\x87\xf4\x0d\xf5$!l\xcb\xbe\x02\xce\xe4\xd0\xd4{\xfa\xba\x85\xac\x11\x8e\xc2/=\x03\xe3\x1aO\xb0p4\x8e\xd8\x96\xcf\x11\x9b\xbc\x1f\x9c\x04o\xc9\x8aaM\xd4\xb0\xe0\x03]\x04\x02 U\x1c!^JL\xb0\xc2\xeeD\xdb\x10\x1dB\x89\xd1\x7f\x93\x91\x8f\xdb:\xc5@IZ\x89\x82\x98\xf3\x1b\x9b\x0e!T\xa7\x91\xf2?1}5\xbe+\x0e\x0cj\x87\xdfsK\x9d\\\xd2r[q\x952\xa3\xacV\xe1\xaa\xb2\xf4\xe5\xad\x01U\x98Q\xca\xd8YU^\x97\xc4\xf1\x13i)\x91\xee\xb7\xc6\xf7\xc0\xf8\x84\x10\xc5\xcf\xf9U\x9e\xdb\x16nENv\x89\xe2\x87\xdcR\xdc\xde3\x19\x9d#\x82%\xf7\xd8Z\x02\xaf\x8c\x92\x1a|\xb05\x07\xfbr\x99\x81\x1bX\xc4\xb9\x89\x18\xf7\x89\x19E\x15B\x02k'\xc4\xc0E\xa7G\x14\x94>u\x80\xff\xe54#\x87I\x1b\x11\x88^\x18\x9a\xae|jh\xbag\xde\x81\x12\xcf\xf7\xb4\xb8\x17f\x17+\xebh\xce\x17\xf7k\x8b7\xc7tA\xaaA\x85J\x9asa\x8d\x03)\xd1z\x0c\x8f1\xe1\xe2\xf4\x18\xdc\xbdx\x07\x16n\xcb\xe5\x8f\x81\xcdY\x1c\x89\xeb-\xd0C\xcf\xc7Um\xc1\xc6\xc2*\\\xdd)A\x06\x90\xd6K\xdb\x03\xe8\xc3\x1f\xc0V\x9fVq\xaa\\\xcetw\x03\x80\xe2o\x8c\xc3\xf3\xf0\xee\xbb\xece\xcf\xc4`\xb5\n#\x12\xc3\xb1e\xef\x11\xefG\xd8\xfa\xcd\xbb?\xa2\xf9jv4\xb4>Z\x8aY\x8c\xf9\xda\xcf\x81\x02\xc8V\xdeC(%\xa6\xbd\x9dZ\x9fp\x03\x9e\x1b\xda\x017\xcf\xdd\x80\xd1\xdf\x89\x98H\x8c\xf4\xe7\x83\xc5X\xb43\x17\xcfM\xec\x8d.\xe1z\xcc=X*~\xb69[\x18\x91\x1e\xa3\x9a\xd19\x1e\xb7w\x8b\xf7X\x01\xcf\xe6\xc2\x1a\xcf\xf7\xfb\x0b\xc5:\x97G965R\xc1\xc9 \x7f&)\xfe`I\xb5\xe7\x85\xd1]\x856z\xa5\xf0\xe8\xda,\xcf\xb3+\xf6(9\x12\x1d\x04F\x07\x8eT\xe0\xde\xfcr\xe8C\x83\x08\xb8TR\x99YkE\xad\x17\x06\xccF\x17\xfd\xb8\x8d\xc0\xe3\xe3\x13f-\xe0\x01X\x1c\xeda\xd2\x89\xfdbB<:\xa5\xa0d;,o\xcc\xab\x08\xf0\xfaF\x19\xf1\xfa\xf6<\xf1\xf1\x1f\xb7 \x83\xe8\x1e.\xef\x10\xa7\x98\xde1\x0e3\xd2#\xc5\xcde\x16\xcf\xcf\x07\x8a\x84\xb1\xedb\x04=\x01\xcd\xcb\xdb\x0e\xe3\xab\xed\xb9R\xaa\xf9(\xd2(\x1e\x1e\xda\x9e4\xac\x08\xbc?\xb6;\x0e\x11\x08\xed\xca*a\x10y\x9e\xe61\xfd\x0f\x84r\xb9q\xa0\xd2\x02\x8d\xec\xcf\xdb\x9a\x897V]\x01|7\xbc\xef\xf7\x03\xbc\xf9\x868\xb86\xcbg\x92P\xfa\xcc\\=|&\x853\x9d\xbadd\x00&\x8bC\xd4\xfe\xd5\xc0q\xce\xe2z\x1f\xb5W\xfd\x1c\x8f\x9fC:\xc9i(\xb4\xd8qQJ$\xde\x8b0\xc1\xca\x9e\x9aZUk^\x1b\x99>\xed\xf1|\xa0?\xca\xda\x06\xf2\xc6\xca\xa0T.\x82\xd36\xee\xfdm9R\x1e\xab\xbfu\x8c&y\xa4/\x9e_\xbd\x1fO\xae\xdc\x8b\x10\x92\xb8?\x98\xd6\x1fWv\x8c\x95\x12#>\xb7.S\xd8\xb9\xe5\x10^\x893#-,\x08=\xa2\x82\x15\xfdbC\x15\x03\xe2C\xa5z\xe2\xbc\x11\xc3E\x96H+\xc0m=\x92a\xd4(\x85\xecJ\xabx\xeb\xa2=\x9e_\xb7\xe5(\xa5\xeae\xa1F\xcer\xfb\x02\x01\xc0\x85\xf4s\xba\xb5\xce\x9efe\xcf.\xce\x97\x15\xa4\xcb&\xed\xe2'\x92`\xde\xa4\xd6\x90\x99!\x8e\x8e\xbf\x84:\x07\xee\x18\xdb\xd5=--B\xf9\xe9\xfeb\xa4\x9a\xf4\xe8J\x8b\x97\xbd\xa3\xe6\x1f,\xc5\xcb4\x7f;i4\xcbv\xe7a\xd9\xbe#xq\xbd\x19cS\xa30\xbdC\x9cpc\xef6Bq\xad\xd7\\\xb7\xbd\xb8F2\x81\xdd\xda+\x05?e\x16c\xc6\xec\xf5\x989\xad\x1f\xaeh\x1b)Un\xbc-\xb7\x8c\xf7a.\xa59\x85\xe0\xe8>\x8cB\x81}\xe5\xb5\xa8\" \xe4\xbe\xbc\x91(S\xab\xa3j\x9ff9:\xc0\xfe}\x10\xd8\x86es\x10\x7f\xeb\xdf\x05\xd0\xefT{8\\\xbd\xf0Zj\xdd\xfc\x18\x8fcN^\xa1v?g\xb2\xee\x12\x11\x84\x01 aX\xb65\x87\xb3P\xb4V-\x84\x0bF\x0d\xc6_\x93=\xf9l\x13;D\xacn\n\x80\xb0]\xff!\x04\xeb\xc7m\xde_\x80{~\xdd\x897Fu\xc1M\x1dc0\xa1m4\xf2\xaa\xacH\x08\xd6#VC\x12\x86C\xa4\xbf\xef\xf2\xa6KO\x0cc\xa6\xea>x\xa4By0\xa7\x14s\x88\x11\xc7\xb6\x89\xc2\x9cI\xbd\xa4\x18\x0f6EI\xf61\xd2\x08\xd2C\x8d\xc2k\x9b\xb2\xf0\xeb\xda\xfd\n\xc4\x85\xb9\x89\xe3\xbeB\xa0\xf1\x90\xf7\xda\xf8\x15\x82\xf0\x7f$\xad\xb0=\x90\xddg\xd9\x0fp\xcf)}d\x15\xc2\xb7(\xabErZ\x94\xfb\xed!m\x15\xcb\x0bj\x84\x9b\xe6nD\x0c\x81\xd9H\x92\x80J\xacv,>P\xc4\xfb0\x02\xc2\x8c<\xd6Zx8\xc9!\xff\xce\xc7\xbf% \x90\xf2\xde(\x14\x0fB\xa5L\xa3>W\x916\xb1\x98\xd5U\xbdZ \xb3N}L\x9a\x0f\x16\xcc\xd9\xa4\x14m\xd0\n\xde~\xc22 \xb0N\xa4=\xf0\xda\x963p\xe2\xd2c\x97\xc1q\x92\xf4$\xe0)\xd8\x9c\x83\xa1Q\x89o]\xd8I\xa4\x1bV\xfc}Y\x86\x14\xdcXH\xa0\xf2\xd5\xef\xfb\xb0x\x9b\xcf\x94k\xd2\xcd\x91\nk\x89\xe2\x8d\xc4\xf0Si\xae\xefp\xc6\xd0 \x8dJ0k\xd5\x82\x95\xe6y\xcb\xe2\x9dXWP\x01\x17\xfd\x7fwi-\x8a\xed\x1e\xdc\xd0=\x89@\xc8\x81}\x156)\xc5|\xa4N\xedMW\xed\xb5\x7f\xffA\x1a\xd2\x96\xe4|X\xad\x9e\xbe\xf7\x99o\xce\x06q\x94\xf87\xcd0\x0egY\x98\xe1g\x1fv\x8b\xfdg#\x19h 1\x0f\xf3\xf9S\xe0\xf8\xae\xc1q\xa1\xd0\x910\x87\x96Q\xea\xd9\x1fbO\xa4\x9eh\x1e\x17\xe2\x96N\xeb\xe0\x8d{;A\xad\x0d\x8cD\xf1\x05\x02\x04\x01!\xfa\xe7\xd6\x1d(\xc0\xbaC%\x88\x894I\x1b\xea\\\xa3\xa3\xa0\xa4\x06p\xba\x00v\xd3S\x08\x8f\xd2\xf9G\xeb\x0c\x90\xae\x8a_\xa0S\x97\x94\xd4Z%\x8d#\xda\xa8E.\x81\x0eK#\xbc\xa8x\x9b \x93\x0b/y\xf7\x0b\xb2\xfc\x98\xd5\x854\xc0\xbd\xc4\xddG\xc3\xee\xd4H\xb5cU\\\xd0\xdd\x86+FtrOJ\nU>\xb21\x07\xbby\xd3.\xcc\xc8Z\xc1\xc30hX\xc2\xab\xa3\xb6\x9c\xc0\xa3~\xf6\xe0BI]S\x08w\xb1n\xc4\x9aC\x9b`\x1d\xf6\x14U\xe1\xbb\xfd\x85\xb8\xa6]\x14\x9d.J%n\x97\x1f.\x83F\xa1@|\x90F2Qq\x90#\xdd\x0c\x8fa=\xf6\x91\xc9\xdc\xf7\x1c\xa1\xeb\xa8-9\xc3\xd7\xe0\xb5\xf8P\x80f\xa7\xfa\xc4\x1e8\x81x(\xf9\x13\xc3\xc2\xd5\xec\xfe\x06\xff\xbc\x848\xcd\xcb\xa7\xc4+\xae\xef@\xe01\x80@d\xf9\xf6\\o\xbcX\xeb\xf8N\xb8\xb4\xc3\xe3\xe7\xc9zg\xed\xf5\x9a\x06\x8d;M\x1aV\x14\x9f'&<\x10f\xc3w\xd0\xa9\xac\x85\xa55\xd8\x93[\xea\x05\x0f\xad\xcaJ\xc7\xe7\x92\x060\x88\xce;\xbe\\b)\xb4\xea\xcc\x1a\xd2\x00^X\x97\x89p\x9d\n]\xa3LRp\x11\xd7\xec\x98\xb9\xa7\x00?\xed\xce\xe3Z |n\xe3\\\x0e\x05\xe1\xdft\x9d%\xa8\xa8\x9b\x00\x87[\x93\x18mF\xb7\xd4(\x98h\xbc\xa4\xd4(\xf7\x1b\xc3\xda+vTX\x85\x97~\xdf'J\xee\xc3\n\x05Kw\xec\x15\xc2\x9b\x80\x1f\xa0\xe1\xd4\xf3\x84\x0c\xa4Q\x95\xd1}\xd1\\\x13\xf5*<5\xbc#~\xd8\x9c\x8d\x7f,\xdb\x87\xac*\x0b\xee\xa1\x9f\xdf\xac\xcf\xc4#\xfd\xd3\x90lP\xd1yu(\xa0\xf3\xb9\x9f\xa4\xa9\xd5#\xb7(\xca rn\xd0Rx\xed\xffg\x8a\xb8\xae\xccp\xdf\xffS\x9a8\x16\x83\x87\xbf>\xb2\xecF\xbc\xd6\xcf>\x97\x06\x02\xc4\xf49\\\xc4\x1e\x90\xc39\xa8\x90\x05F\xb1\xc5k\xe8\x8b\xe1\xcd\x1bu>\x80\x07g\xf2\xb8\xf6d\xe0\xd14\x0d\xa4\xbej#b:1\xe4h\xe85\\O\x80\x93\xa7U\xc3\x9b\xbc\xb0\xf0\xe4\x0c\x1f\xd7\x13w_5\x9f\xa4\x8e\x89v\x97gzz4\xda\x84\x05)\xfaD\x07\xbb?\xdc\x91\x0bO\xb5U\x89\xa8\xe0%$\xe6\xff\xdc\x08\xf0x\x82\xb4\x9d\xc78q\xe3\xb0Nq\xb8\xa5{2\xbaD\x06K\x80\x94YQ\x07\x8dJ\xa9d\xd3\xd1\xb4\x1f\xb6z\\%5\n\xc4\x9a\xb3\xe0\xf6<\xd4\xa8\x07\xa8V\xaeF\x85u\xc8G\xbb\xf20>5\x02w\xf7J\x86\xdb\xed\xc1\xab\x04|\xb3v\x1d\x86\xc5#\xe2\xc9\xb1\xddqg\xcfd\xd4\xd2\xd7\xf0\x11\x1d\x93\x12H\x86\x06\xad\xa7\xaf!\xffO\xf4p#)X\x8f\x10\x9a\x13\x07Q\xc9\xd4\xea\x89\xed\xf8\xec[\xdf\xdcAc\xbc\x9f0\x06\x7f\xda\xd4\x9b\xb2X\xd8\x0b\xd0_\xcf \x8eW\xb9#@\x8d\x89\x05\xc5G\xfc\xe9Dp\xf1]a\x9d-\xe2\x82\xc4p\xdb+\x91&\xd4q= \x9d\xba%\xbe\xefe>\xa1a\xe1y\xb0\xb6\xd9$\xf7\x1f\x9fp}\xcaJ\xb4\xcd\xe97W\xe4k\x8d\xd4^\xb0\x1aJ\xc5-\x08\xd2\xfeg\xe5\x9e|\xc5\xca\xf5\x99\xe2\xcd\xe3\xbbcL\xa2\xd9-\xc9 Z\x95\x92\xc0\xe3\xedF\x8c\xd4\x0b\x1e\xcf\x93\xa8\xb5\xe3\xaa\x01m\xf1\xc6\xc8\xce\x08\xa7\xbb\xcaq\x88\xc8&M \x8c4\x10v\x0f.\xb1:\x91n6*\x0e\xa8\x95\xbc?\x11B+7\x0d^\xfb\xed\xe9\xb4\xacG\x08\xe8V\xfcJ\xa0\xf6d\x84 \xcf\x0cN\xc3\x93\x03\xda`b\xbb\x18\xe4\xf0\xc6|x\x10z\x87\xe9\xa5t\xc2\x8f\xae\xce\xc4o\xbc\x19(UZ\xab\xb7o\xc3Z\x07IY\xdd\"\x82\xa5\x18\x99\xe3\xb27\x18\x03x\xd6\x0d\xa5 \xd7\xf99\x86\xa1\x19\xdey\xa8\x9fs>\x9dx\x19\xe6\xc7xa~\xce\xd5_\xaedj\xc49\x1c\xc5\xcc\xb9\xa1^\xf4\x99\x8a\x9aJ\x9fR\xe3\xd2\x02\xf5M\x9f1~\xf4\x0f\xa9\xf7\x7f^\xdf\xdf\x060\x87\xcb\x9b0\x7f\xde\x0b\x99\xe1\xbbvc\xc9Xas.\xe9\x1aa\x1a<&%\x12\xf3H\x9b'A4\xac\x85\xa8\xea{|\x1a\xc7\xd7\xf0\xee\x014\x17\xb5D\x84\xac\x04\x9b\xf1\xbd{|\xb3\xa9Y\x1a\xd3\xe9\xafu\xbc\xe6hmA\xd8A\x0cz&\x81@j\x88F\x0d\xab\x07J\x9b\xdb#\xf8\xf6?N\xef\x16'\xe0%TZ\xd1\xbfc\x9c\x04\x1ez\xc2\x87\x0fv\x15\xe0\xdf\x8bw &:\x04\xef\x8d\xe9*\xedU\xf0\x1e\xc5\x7f\xc7v\xc5$\xab\x1d\x9b\xf7\x15\x84\xc3lx\x9b\x18\xfb\xf8F\xccr%i!\x1fB\xab\xbe\xf5\xd5e\x19(\xa8\xb2\xe0\xba\xeeI\xe8L`\xd2.T\x8f\x1a\xbb\x07\xbf\xe6W\xe1s\xd2\xa4fn\xc9\xf6\xfa\xb2\xab\x95\x1f\xd0E\x97\xff1\x82\xd3%\xc5\xad\x0c\x8e7K\x11\xb8\xc2\x89\xe6\x8a\x1a?\x9f\\Y\x03\xc7j\xfc\x1c\xa7\xb2\x19\xde`\xbe\x1f\x8c\xbc\xae\x11\xef\x937\xa7\x1b\x9b+\xcd\xdf\xb4\"6?\x9fOc#\xc7Y\xc8a3\xeb\xfd\xd4\xae\x84\xffE\xa0x\xe7x\x0e\xbc\xd1\xdd\x0d\x95?]\xcf\xfa+N_1\x93\x99R\xd6\x9f\x82\xbd\x14\xfc\x07?\xef\xf9K4P\x8a\xd6O\xba\xc47F\xa3=\xc7\x04A\x18ds\xbb/\x1f\x9d\x1c\xf1\xcd\xbc\x1d\xb9\"\xdc\x9e\xc3\xf4\xfd\xc7\x9fENT\xe3\xd3\xf8\xb8\xed\x86\xd71\x87c~v\x9c\xa1\xeb\xd9\x02\xf8\xe6\x9b\x8b<>\xfe\xc1\xdfn\xaeO\x00\xda\xe2\xbb_\xbfyBK\x88\xdcaS\xcf\x1e\xa8\x94\xa9\xa1:\xb5hq\x89J\x8e\xb5\x80\xa08\xfa\xa0OE\x91\xa4M\x8cd\xff\xf1\xdb{$K\x9a\xc7{\x04\x1ew\xce\xdb(i\x08W\xf6I\x95\xd2\xa8\xdc\xfe\xdb.\xf4\x8b1\xe3\xc9~)\xb8\xbd{2n\xe2t'.\xf1\"(\x05\x96\xa0O_\xf7\x9d\xeb\xa5\xeb\xd5j:\xff\x86\x99\x1b\x0eb\xd6\x81B\xf4\x8d5K\x0e\x03\xe56'6\x15VB\xac\xa8\xf3\x96\xe1\xd5(?\xa1\xf3o?\xb6\xbf\x07j5\xa7\xa4WJ\x9b\xf1\xc7\x11K\xafo\xf8\xf9\xcc\x1aJa\xcaR\xd2\x02?\x17qS\xe9\"x\x83\xe1\x1a\xa7szM\x9b\xa7\xa2\xfeh\xfc\xbe\x9c\xbf>\xf7l\xd3O\xf2\xe3|\x7fLG\x0cf\x1cA\xfe\x98\xcf\xfc\xc4y\x96\xba\xf9\xc0\x90\xcb\x03h\x8f{wY\xbe\x0f\x97\x01\xe3\x17\x9c\xda\xab\xeb\x8a\x00\xdf\x0d\x07\xff\xdd\x18\x80\x14\xdaT\xda \xef\xbeM\xa3y\x0b\xa1\x1d\x7f\xf3A\x9c\xe6\x07:\xb5\x07.w\x7f(T\x8a\xb3\xc8\x83,M4\x15\x06\xc0\xf3\xfcZ\x8b\xcd\x0d \xd5\xcd5XK \xfd\x0c\xe7e\x14DL\x96\xeb\x86\xdb\xb8\xd4\xa5W\x039\xdd\x82\x96\nN\xc5\x128\xf4\x8c\x0cF\xbe\xcd\x85\x87W\xef\xc5\xd8n\x89X0\xb9'2k\x9d\x12\xd7*\xac\xb3\xe3\xddm9\xb8\xa3G\"zD\x9a\xbcq\x1a\xa55\x02\xa9\xca\xec\x82\xb7\xb4q\x8f]\xbc\x91@n \xc2\x8c\x0f\x8avW\xf7\x0d\x9c\xbf\x87mQY\x81N\xe1A\xd8VX\x89 \x1d\xe3\xf0\xf8\x80t)\xde\x7fAv\x89T\x10\n\xa1F\xde\xf4.\x94_\x99L2\xc9$\xd3\xf9 uP(\xde\x86Ry\xdf\xab\xbf\xef\xc3\x90\x840\x0c\x8f2b\xce\xf4~\xf8rG.\xf6\x96\xd6\xe0\xeanI\x98\xd19\x01q\x1a\x01\x9f\xed/\xc1\xcc\xcd\xd9G\x0bK\xbd\"\xbf.\x99d\x92I\xa6\xf3\x17@x\xf3\xe3Q\x98t7TT\xd4\x85^1g\x03\xde\x1e\xdb\x15\xa3\x92#\xf0\xcc\xa0?K\x08\x14\xdaE\xbc\xb3#\x1f\xf7\xff\xb6\x8b\xbd\xaf\xd8{j]\x83I\ne\x92I&\x99d:\x8f\x00\x84\xd3\x88{\xc4\xe10\x1b\xd7\x15\x94\xd6\x18\xa6}\xb7\x01\x13\xda\xc7\xa1Gt\x88TA\x90\xab\xf5\xad\xcd+\xc7\xea\x03\x85\xde\x0d\xf7`\xfd^:\x7f\x8c\xfc\xaad\x92I&\x99d\x00a\xdaI\x9aH7\x98\x0d\x1f\xc2\xee\x1a\xf9\xe3\xb6C\xf8\x91\xeb\x7fp \x00\x97\xdb{F\x90\x8e~W~N\xe0\xc1U\xdf\xec\xf2\xab\x92I&\x99d\x92\x01\xe4(\x1d$p\x18\x05\xb5r\x14i#\x17CDw@4\x92\xdaQ A\xaa\x8e5\x8f@f\xb3\xfc\x8ad\x92I&\x99Z&\xfd\xbf\x00\x03\x00\x93\x19\xf9\xc5\x1e\x83\x05U\x00\x00\x00\x00IEND\xaeB`\x82PK\x07\x08z\x1b\xa9\xd9?M\x00\x00?M\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\xd7\x88\x05I\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00index.html\n\n\n \n \n \n \n \n \n\n InfluxDB - Admin Interface\n\n \n \n \n \n\n\n\n\n
\n \n \n\n\n \n
\n\n \n
\n
\n
\n

Connection Settings

\n
\n
\n
\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n
\n
\n
\n
\n
\n \n \n
    \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n
\n\n \n
\n
\n

InfluxDB Admin UI: Server:

\n
\n
\n\n \n
\n
\n
\n
\n \n

Write Data to InfluxDB

\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n
\n\n \n
\n
\n
\n
\n \n

URL for the Query

\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n\n \n \n \n \n\n\n\nPK\x07\x08\xf5\xa95\xd6\xda-\x00\x00\xda-\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\xd7\x88\x05I\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00js/admin.js// allow the user to store recent queries for quick retrieval\nvar recentQueries = [];\nvar queryPointer = null;\n\n// keep track of the databases that exist on the server\nvar availableDatabases = [];\nvar currentlySelectedDatabase = null;\n\n// connection settings for the server, with sensible defaults\nvar connectionSettings = {\n hostname: (window.location.hostname ? window.location.hostname: \"localhost\"),\n port: \"8086\",\n username: \"\",\n password: \"\",\n ssl: ('https:' == window.location.protocol ? true : false)\n}\n\nvar connectionString = function() {\n var protocol = (connectionSettings.ssl ? \"https\" : \"http\");\n var host = connectionSettings.hostname + \":\" + connectionSettings.port;\n\n if (connectionSettings.username !== \"\") {\n $.ajaxSetup({\n headers: {\n 'Authorization': \"Basic \" + btoa(connectionSettings.username + \":\" + connectionSettings.password)\n }\n });\n }\n\n return protocol + \"://\" + host;\n}\n\nvar getSeriesFromJSON = function(data) {\n var results = [];\n data.results.forEach(function(result) {\n if (result.series) {\n result.series.forEach(function(s) {\n results.push(s);\n });\n }\n });\n return results.length > 0 ? results : null;\n}\n\n// gets settings from the browser's localStorage and sets defaults if they aren't found\nvar loadSettings = function() {\n var cs = localStorage.getItem(\"connectionSettings\");\n\n if (cs != null) { connectionSettings = JSON.parse(cs); }\n\n document.getElementById('hostname').value = connectionSettings.hostname;\n document.getElementById('port').value = connectionSettings.port;\n document.getElementById('username').value = connectionSettings.username;\n document.getElementById('password').value = connectionSettings.password;\n document.getElementById('ssl').checked = connectionSettings.ssl;\n\n getClientVersion();\n getDatabases();\n}\n\nvar updateSettings = function() {\n var hostname = document.getElementById('hostname').value;\n var port = document.getElementById('port').value;\n var username = document.getElementById('username').value;\n var password = document.getElementById('password').value;\n var ssl = document.getElementById('ssl').checked;\n\n if (hostname == \"\") { hostname = \"localhost\"; }\n\n if (port == \"\") { port = \"8086\"; }\n\n connectionSettings.hostname = hostname;\n connectionSettings.port = port;\n connectionSettings.username = username;\n connectionSettings.password = password;\n connectionSettings.ssl = ssl;\n\n localStorage.setItem(\"connectionSettings\", JSON.stringify(connectionSettings));\n\n getDatabases();\n}\n\nvar showSettings = function() {\n $(\"#settings\").show();\n $(\"input#query\").prop('disabled', true);\n}\n\nvar hideSettings = function() {\n $(\"#settings\").hide();\n $(\"input#query\").prop('disabled', false);\n}\n\n// hide errors within the Write Data modal\nvar hideModalError = function() {\n $(\"div#modal-error\").empty().hide();\n}\n\n// show errors within the Write Data modal\nvar showModalError = function(message) {\n hideModalSuccess();\n\n $(\"div#modal-error\").html(\"

\" + message + \"

\").show();\n}\n\n// hide success messages within the Write Data modal\nvar hideModalSuccess = function() {\n $(\"div#modal-success\").empty().hide();\n}\n\n// show success messages within the Write Data modal\nvar showModalSuccess = function(message) {\n hideModalError();\n\n $(\"div#modal-success\").html(\"

\" + message + \"

\").show();\n}\n\n// hide errors from queries\nvar hideQueryError = function() {\n $(\"div#query-error\").empty().hide();\n}\n\n// show errors from queries\nvar showQueryError = function(message) {\n hideQuerySuccess();\n\n $(\"div#query-error\").html(\"

\" + message + \"

\").show();\n}\n\n// hide success messages from queries\nvar hideQuerySuccess = function() {\n $(\"div#query-success\").empty().hide();\n}\n\n// show success messages from queries\nvar showQuerySuccess = function(message) {\n hideQueryError();\n\n $(\"div#query-success\").html(\"

\" + message + \"

\").show();\n}\n\n// hide warning from database lookup\nvar hideDatabaseWarning = function() {\n $(\"div#database-warning\").empty().hide();\n}\n\n// show warning from database lookup\nvar showDatabaseWarning = function(message) {\n $(\"div#database-warning\").html(\"

\" + message + \"

\").show();\n}\n\n// clear out the results table\nvar clearResults = function() {\n $(\"div#table\").empty();\n}\n\n// handle submissions of the query bar\nvar handleSubmit = function(e) {\n var queryElement = document.getElementById('query');\n var q = queryElement.value;\n\n clearResults();\n hideQueryError();\n hideQuerySuccess();\n\n if (q == \"\") { return };\n\n var query = $.get(connectionString() + \"/query\", {q: q, db: currentlySelectedDatabase}, function() {\n });\n\n recentQueries.push(q);\n queryPointer = recentQueries.length - 1;\n\n query.fail(handleRequestError);\n\n query.done(function (data) {\n var firstRow = data.results[0];\n if (firstRow.error) {\n showQueryError(\"Server returned error: \" + firstRow.error);\n return\n }\n\n var series = getSeriesFromJSON(data);\n\n if (series == null) {\n showQuerySuccess(\"Success! (no results to display)\");\n getDatabases();\n return\n }\n\n hideDatabaseWarning();\n React.render(\n React.createElement(DataTable, {series: series}),\n document.getElementById('table')\n );\n });\n\n if (e != null) { e.preventDefault(); }\n return false;\n};\n\nvar handleRequestError = function(e) {\n var errorText = e.status + \" \" + e.statusText;\n showDatabaseWarning(\"Unable to fetch list of databases.\");\n\n if (\"responseText\" in e) {\n try { errorText = \"Server returned error: \" + JSON.parse(e.responseText).error; } catch(e) {}\n }\n\n if (e.status == 400) {\n hideSettings();\n } else if (e.status == 401) {\n if (errorText.indexOf(\"error authorizing query\") > -1) {\n hideSettings();\n $(\"input#query\").val(\"CREATE USER WITH PASSWORD '' WITH ALL PRIVILEGES\").focus();\n } else {\n showSettings();\n $(\"input#username\").focus();\n }\n } else {\n showSettings();\n $(\"input#hostname\").focus();\n showDatabaseWarning(\"Hint: the InfluxDB API runs on port 8086 by default\");\n errorText = e.status + \" \" + e.statusText + \" - Could not connect to \" + connectionString();\n }\n showQueryError(errorText);\n};\n\nvar handleKeypress = function(e) {\n var queryElement = document.getElementById('query');\n\n // Enable/Disable the generate permalink button\n if(queryElement.value == \"\" && !$(\"#generate-query-url\").hasClass(\"disabled\")) {\n $(\"#generate-query-url\").addClass(\"disabled\");\n } else {\n $(\"#generate-query-url\").removeClass(\"disabled\");\n }\n\n // key press == enter\n if (e.keyCode == 13) {\n e.preventDefault();\n handleSubmit();\n return false;\n }\n\n // if we don't have any recent queries, ignore the arrow keys\n if (recentQueries.length == 0 ) { return }\n\n // key press == up arrow\n if (e.keyCode == 38) {\n clearResults()\n hideQuerySuccess()\n hideQueryError()\n\n // TODO: stash the current query, if there is one?\n if (queryPointer == recentQueries.length - 1) {\n // this is buggy.\n //recentQueries.push(queryElement.value);\n //queryPointer = recentQueries.length - 1;\n }\n\n if (queryPointer != null && queryPointer > 0) {\n queryPointer -= 1;\n queryElement.value = recentQueries[queryPointer];\n }\n }\n\n // key press == down arrow\n if (e.keyCode == 40) {\n if (queryPointer != null && queryPointer < recentQueries.length - 1) {\n queryPointer += 1;\n queryElement.value = recentQueries[queryPointer];\n }\n }\n};\n\nvar QueryError = React.createClass({\n render: function() {\n return React.createElement(\"div\", {className: \"alert alert-danger\"}, this.props.message)\n }\n});\n\nvar stringifyTags = function(tags) {\n var tagStrings = [];\n\n for(var index in tags) {\n tagStrings.push(index + \":\" + tags[index]);\n }\n\n return tagStrings.join(\", \");\n}\n\nvar DataTable = React.createClass({\n render: function() {\n var tables = this.props.series.map(function(series) {\n return React.createElement(\"div\", null,\n React.createElement(\"h1\", null, series.name),\n React.createElement(\"h2\", null, stringifyTags(series.tags)),\n React.createElement(\"table\", {className: \"table\"},\n React.createElement(TableHeader, {data: series.columns}),\n React.createElement(TableBody, {data: series})\n )\n );\n });\n\n return React.createElement(\"div\", null, tables);\n }\n});\n\nvar TableHeader = React.createClass({\n render: function() {\n var headers = this.props.data.map(function(column) {\n return React.createElement(\"th\", null, column);\n });\n\n return React.createElement(\"tr\", null, headers);\n }\n});\n\nvar TableBody = React.createClass({\n render: function() {\n if (this.props.data.values) {\n var tableRows = this.props.data.values.map(function (row) {\n return React.createElement(TableRow, {data: row});\n });\n }\n\n return React.createElement(\"tbody\", null, tableRows);\n }\n});\n\nvar TableRow = React.createClass({\n render: function() {\n var tableData = this.props.data.map(function (data, index) {\n if (index == 0) {\n return React.createElement(\"td\", {className: \"timestamp\"}, null, data);\n } else {\n return React.createElement(\"td\", null, pretty(data));\n }\n });\n\n return React.createElement(\"tr\", null, tableData);\n }\n});\n\nvar pretty = function(val) {\n if (typeof val == 'string') {\n return \"\\\"\" + val + \"\\\"\";\n } else if (typeof val == 'boolean' ){\n return val.toString();\n } else {\n return val;\n }\n}\n\nvar getClientVersion = function () {\n var query = $.get(window.location.origin + window.location.pathname);\n\n query.fail(handleRequestError);\n\n query.done(function (data, status, xhr) {\n var version = xhr.getResponseHeader('X-InfluxDB-Version');\n if (version.indexOf(\"unknown\") == -1) {\n version = 'v' + version;\n console.log('got client version '+version);\n $('#influxdb-doc-link').attr('href', 'https://docs.influxdata.com/influxdb/'+version+'/introduction/getting_started/');\n }\n $('.influxdb-client-version').html(version);\n });\n}\n\nvar chooseDatabase = function (databaseName) {\n currentlySelectedDatabase = databaseName;\n document.getElementById(\"content-current-database\").innerHTML = currentlySelectedDatabase;\n}\n\nvar getDatabases = function () {\n var q = \"SHOW DATABASES\";\n var query = $.get(connectionString() + \"/query\", {q: q, db: currentlySelectedDatabase});\n\n query.fail(handleRequestError);\n\n query.done(function (data, status, xhr) {\n // Set version of the InfluxDB server\n var version = xhr.getResponseHeader('X-InfluxDB-Version');\n if (version.indexOf(\"unknown\") == -1) {\n version = \"v\" + version;\n }\n $('.influxdb-version').html(version);\n\n hideSettings();\n hideDatabaseWarning();\n\n var firstRow = data.results[0];\n if (firstRow.error) {\n showDatabaseWarning(firstRow.error);\n return;\n }\n\n var series = getSeriesFromJSON(data);\n var values = series[0].values;\n\n if ((values == null) || (values.length == 0)) {\n availableDatabases = [];\n updateDatabaseList();\n\n showDatabaseWarning(\"No databases found.\")\n } else {\n availableDatabases = values.map(function(value) {\n return value[0];\n }).sort();\n\n if (currentlySelectedDatabase == null) {\n chooseDatabase(availableDatabases[0]);\n } else if (availableDatabases.indexOf(currentlySelectedDatabase) == -1) {\n chooseDatabase(availableDatabases[0]);\n }\n updateDatabaseList();\n }\n });\n}\n\nvar updateDatabaseList = function() {\n var databaseList = $(\"ul#content-database-list\");\n\n databaseList.empty();\n availableDatabases.forEach(function(database) {\n var li = $(\"
  • \" + database + \"
  • \");\n databaseList.append(li);\n });\n\n if (availableDatabases.length == 0) {\n document.getElementById(\"content-current-database\").innerHTML = \"…\";\n }\n}\n\nvar generateQueryURL = function() {\n var q = document.getElementById('query').value;\n\n var query = connectionString() + \"/query?\";\n var queryParams = {q: q, db: currentlySelectedDatabase};\n query += $.param(queryParams);\n\n var textarea = $(\"#query-url\");\n textarea.val(query);\n}\n\n// when the page is ready, start everything up\n$(document).ready(function () {\n loadSettings();\n\n // bind to the settings cog in the navbar\n $(\"#action-settings\").click(function (e) {\n $(\"#settings\").toggle();\n });\n\n // bind to the save button in the settings form\n $(\"#form-settings\").submit(function (e) {\n updateSettings();\n });\n\n // bind to the items in the query template dropdown\n $(\"ul#action-template label\").click(function (e) {\n var el = $(e.target);\n $(\"input#query\").val(el.data(\"query\")).focus();\n });\n\n $(\"ul#content-database-list\").on(\"click\", function(e) {\n if (e.target.tagName != \"A\") { return; }\n\n chooseDatabase(e.target.innerHTML);\n e.preventDefault();\n })\n\n // load the Write Data modal\n $(\"button#action-send\").click(function (e) {\n var data = $(\"textarea#content-data\").val();\n\n var startTime = new Date().getTime();\n var write = $.post(connectionString() + \"/write?db=\" + currentlySelectedDatabase, data, function() {\n });\n\n write.fail(function (e) {\n if (e.status == 400) {\n showModalError(\"Failed to write: \" + e.responseText)\n }\n else {\n showModalError(\"Failed to contact server: \" + e.statusText)\n }\n });\n\n write.done(function (data) {\n var endTime = new Date().getTime();\n var elapsed = endTime - startTime;\n showModalSuccess(\"Write succeeded. (\" + elapsed + \"ms)\");\n });\n\n });\n\n // Enable auto select of the text in modal\n $('#queryURLModal').on('shown.bs.modal', function () {\n var textarea = $(\"#query-url\");\n textarea.focus();\n textarea.select();\n });\n\n //bind to the generate permalink button\n $(\"#generate-query-url\").click(function (e) {\n generateQueryURL();\n });\n\n // handle submit actions on the query bar\n var form = document.getElementById('query-form');\n form.addEventListener(\"submit\", handleSubmit);\n\n // handle keypresses on the query bar so we can get arrow keys and enter\n var query = document.getElementById('query');\n query.addEventListener(\"keydown\", handleKeypress);\n\n // make sure we start out with the query bar in focus\n document.getElementById('query').focus();\n})\nPK\x07\x08\xf2\x1b6\xbft<\x00\x00t<\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00js/vendor/bootstrap-3.3.5.min.js/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under the MIT license\n */\nif(\"undefined\"==typeof jQuery)throw new Error(\"Bootstrap's JavaScript requires jQuery\");+function(a){\"use strict\";var b=a.fn.jquery.split(\" \")[0].split(\".\");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error(\"Bootstrap's JavaScript requires jQuery version 1.9.1 or higher\")}(jQuery),+function(a){\"use strict\";function b(){var a=document.createElement(\"bootstrap\"),b={WebkitTransition:\"webkitTransitionEnd\",MozTransition:\"transitionend\",OTransition:\"oTransitionEnd otransitionend\",transition:\"transitionend\"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(\"bsTransitionEnd\",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var c=a(this),e=c.data(\"bs.alert\");e||c.data(\"bs.alert\",e=new d(this)),\"string\"==typeof b&&e[b].call(c)})}var c='[data-dismiss=\"alert\"]',d=function(b){a(b).on(\"click\",c,this.close)};d.VERSION=\"3.3.5\",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger(\"closed.bs.alert\").remove()}var e=a(this),f=e.attr(\"data-target\");f||(f=e.attr(\"href\"),f=f&&f.replace(/.*(?=#[^\\s]*$)/,\"\"));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(\".alert\")),g.trigger(b=a.Event(\"close.bs.alert\")),b.isDefaultPrevented()||(g.removeClass(\"in\"),a.support.transition&&g.hasClass(\"fade\")?g.one(\"bsTransitionEnd\",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on(\"click.bs.alert.data-api\",c,d.prototype.close)}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.button\"),f=\"object\"==typeof b&&b;e||d.data(\"bs.button\",e=new c(this,f)),\"toggle\"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION=\"3.3.5\",c.DEFAULTS={loadingText:\"loading...\"},c.prototype.setState=function(b){var c=\"disabled\",d=this.$element,e=d.is(\"input\")?\"val\":\"html\",f=d.data();b+=\"Text\",null==f.resetText&&d.data(\"resetText\",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),\"loadingText\"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle=\"buttons\"]');if(b.length){var c=this.$element.find(\"input\");\"radio\"==c.prop(\"type\")?(c.prop(\"checked\")&&(a=!1),b.find(\".active\").removeClass(\"active\"),this.$element.addClass(\"active\")):\"checkbox\"==c.prop(\"type\")&&(c.prop(\"checked\")!==this.$element.hasClass(\"active\")&&(a=!1),this.$element.toggleClass(\"active\")),c.prop(\"checked\",this.$element.hasClass(\"active\")),a&&c.trigger(\"change\")}else this.$element.attr(\"aria-pressed\",!this.$element.hasClass(\"active\")),this.$element.toggleClass(\"active\")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on(\"click.bs.button.data-api\",'[data-toggle^=\"button\"]',function(c){var d=a(c.target);d.hasClass(\"btn\")||(d=d.closest(\".btn\")),b.call(d,\"toggle\"),a(c.target).is('input[type=\"radio\"]')||a(c.target).is('input[type=\"checkbox\"]')||c.preventDefault()}).on(\"focus.bs.button.data-api blur.bs.button.data-api\",'[data-toggle^=\"button\"]',function(b){a(b.target).closest(\".btn\").toggleClass(\"focus\",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.carousel\"),f=a.extend({},c.DEFAULTS,d.data(),\"object\"==typeof b&&b),g=\"string\"==typeof b?b:f.slide;e||d.data(\"bs.carousel\",e=new c(this,f)),\"number\"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(\".carousel-indicators\"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on(\"keydown.bs.carousel\",a.proxy(this.keydown,this)),\"hover\"==this.options.pause&&!(\"ontouchstart\"in document.documentElement)&&this.$element.on(\"mouseenter.bs.carousel\",a.proxy(this.pause,this)).on(\"mouseleave.bs.carousel\",a.proxy(this.cycle,this))};c.VERSION=\"3.3.5\",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:\"hover\",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(\".item\"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d=\"prev\"==a&&0===c||\"next\"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e=\"prev\"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(\".item.active\"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one(\"slid.bs.carousel\",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?\"next\":\"prev\",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(\".next, .prev\").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide(\"next\")},c.prototype.prev=function(){return this.sliding?void 0:this.slide(\"prev\")},c.prototype.slide=function(b,d){var e=this.$element.find(\".item.active\"),f=d||this.getItemForDirection(b,e),g=this.interval,h=\"next\"==b?\"left\":\"right\",i=this;if(f.hasClass(\"active\"))return this.sliding=!1;var j=f[0],k=a.Event(\"slide.bs.carousel\",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(\".active\").removeClass(\"active\");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass(\"active\")}var m=a.Event(\"slid.bs.carousel\",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass(\"slide\")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one(\"bsTransitionEnd\",function(){f.removeClass([b,h].join(\" \")).addClass(\"active\"),e.removeClass([\"active\",h].join(\" \")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass(\"active\"),f.addClass(\"active\"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr(\"data-target\")||(d=e.attr(\"href\"))&&d.replace(/.*(?=#[^\\s]+$)/,\"\"));if(f.hasClass(\"carousel\")){var g=a.extend({},f.data(),e.data()),h=e.attr(\"data-slide-to\");h&&(g.interval=!1),b.call(f,g),h&&f.data(\"bs.carousel\").to(h),c.preventDefault()}};a(document).on(\"click.bs.carousel.data-api\",\"[data-slide]\",e).on(\"click.bs.carousel.data-api\",\"[data-slide-to]\",e),a(window).on(\"load\",function(){a('[data-ride=\"carousel\"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){\"use strict\";function b(b){var c,d=b.attr(\"data-target\")||(c=b.attr(\"href\"))&&c.replace(/.*(?=#[^\\s]+$)/,\"\");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data(\"bs.collapse\"),f=a.extend({},d.DEFAULTS,c.data(),\"object\"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data(\"bs.collapse\",e=new d(this,f)),\"string\"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle=\"collapse\"][href=\"#'+b.id+'\"],[data-toggle=\"collapse\"][data-target=\"#'+b.id+'\"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION=\"3.3.5\",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass(\"width\");return a?\"width\":\"height\"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass(\"in\")){var b,e=this.$parent&&this.$parent.children(\".panel\").children(\".in, .collapsing\");if(!(e&&e.length&&(b=e.data(\"bs.collapse\"),b&&b.transitioning))){var f=a.Event(\"show.bs.collapse\");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,\"hide\"),b||e.data(\"bs.collapse\",null));var g=this.dimension();this.$element.removeClass(\"collapse\").addClass(\"collapsing\")[g](0).attr(\"aria-expanded\",!0),this.$trigger.removeClass(\"collapsed\").attr(\"aria-expanded\",!0),this.transitioning=1;var h=function(){this.$element.removeClass(\"collapsing\").addClass(\"collapse in\")[g](\"\"),this.transitioning=0,this.$element.trigger(\"shown.bs.collapse\")};if(!a.support.transition)return h.call(this);var i=a.camelCase([\"scroll\",g].join(\"-\"));this.$element.one(\"bsTransitionEnd\",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass(\"in\")){var b=a.Event(\"hide.bs.collapse\");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass(\"collapsing\").removeClass(\"collapse in\").attr(\"aria-expanded\",!1),this.$trigger.addClass(\"collapsed\").attr(\"aria-expanded\",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass(\"collapsing\").addClass(\"collapse\").trigger(\"hidden.bs.collapse\")};return a.support.transition?void this.$element[c](0).one(\"bsTransitionEnd\",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass(\"in\")?\"hide\":\"show\"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle=\"collapse\"][data-parent=\"'+this.options.parent+'\"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass(\"in\");a.attr(\"aria-expanded\",c),b.toggleClass(\"collapsed\",!c).attr(\"aria-expanded\",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on(\"click.bs.collapse.data-api\",'[data-toggle=\"collapse\"]',function(d){var e=a(this);e.attr(\"data-target\")||d.preventDefault();var f=b(e),g=f.data(\"bs.collapse\"),h=g?\"toggle\":e.data();c.call(f,h)})}(jQuery),+function(a){\"use strict\";function b(b){var c=b.attr(\"data-target\");c||(c=b.attr(\"href\"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\\s]*$)/,\"\"));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass(\"open\")&&(c&&\"click\"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event(\"hide.bs.dropdown\",f)),c.isDefaultPrevented()||(d.attr(\"aria-expanded\",\"false\"),e.removeClass(\"open\").trigger(\"hidden.bs.dropdown\",f))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data(\"bs.dropdown\");d||c.data(\"bs.dropdown\",d=new g(this)),\"string\"==typeof b&&d[b].call(c)})}var e=\".dropdown-backdrop\",f='[data-toggle=\"dropdown\"]',g=function(b){a(b).on(\"click.bs.dropdown\",this.toggle)};g.VERSION=\"3.3.5\",g.prototype.toggle=function(d){var e=a(this);if(!e.is(\".disabled, :disabled\")){var f=b(e),g=f.hasClass(\"open\");if(c(),!g){\"ontouchstart\"in document.documentElement&&!f.closest(\".navbar-nav\").length&&a(document.createElement(\"div\")).addClass(\"dropdown-backdrop\").insertAfter(a(this)).on(\"click\",c);var h={relatedTarget:this};if(f.trigger(d=a.Event(\"show.bs.dropdown\",h)),d.isDefaultPrevented())return;e.trigger(\"focus\").attr(\"aria-expanded\",\"true\"),f.toggleClass(\"open\").trigger(\"shown.bs.dropdown\",h)}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(\".disabled, :disabled\")){var e=b(d),g=e.hasClass(\"open\");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger(\"focus\"),d.trigger(\"click\");var h=\" li:not(.disabled):visible a\",i=e.find(\".dropdown-menu\"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:\"\",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:\"\"})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:\"\",paddingRight:\"\"})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
    ',trigger:\"hover focus\",title:\"\",delay:0,html:!1,container:!1,viewport:{selector:\"body\",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error(\"`selector` option must be specified when initializing \"+this.type+\" on the window.document object!\");for(var e=this.options.trigger.split(\" \"),f=e.length;f--;){var g=e[f];if(\"click\"==g)this.$element.on(\"click.\"+this.type,this.options.selector,a.proxy(this.toggle,this));else if(\"manual\"!=g){var h=\"hover\"==g?\"mouseenter\":\"focusin\",i=\"hover\"==g?\"mouseleave\":\"focusout\";this.$element.on(h+\".\"+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+\".\"+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:\"manual\",selector:\"\"}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&\"number\"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data(\"bs.\"+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data(\"bs.\"+this.type,c)),b instanceof a.Event&&(c.inState[\"focusin\"==b.type?\"focus\":\"hover\"]=!0),c.tip().hasClass(\"in\")||\"in\"==c.hoverState?void(c.hoverState=\"in\"):(clearTimeout(c.timeout),c.hoverState=\"in\",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){\"in\"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data(\"bs.\"+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data(\"bs.\"+this.type,c)),b instanceof a.Event&&(c.inState[\"focusout\"==b.type?\"focus\":\"hover\"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState=\"out\",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){\"out\"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event(\"show.bs.\"+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr(\"id\",g),this.$element.attr(\"aria-describedby\",g),this.options.animation&&f.addClass(\"fade\");var h=\"function\"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\\s?auto?\\s?/i,j=i.test(h);j&&(h=h.replace(i,\"\")||\"top\"),f.detach().css({top:0,left:0,display:\"block\"}).addClass(h).data(\"bs.\"+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger(\"inserted.bs.\"+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h=\"bottom\"==h&&k.bottom+m>o.bottom?\"top\":\"top\"==h&&k.top-mo.width?\"left\":\"left\"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr(\"data-original-title\")||(\"function\"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+\" `template` option must consist of exactly 1 top-level element!\");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(\".tooltip-arrow\")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data(\"bs.\"+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data(\"bs.\"+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass(\"in\")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off(\".\"+a.type).removeData(\"bs.\"+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.popover\"),f=\"object\"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data(\"bs.popover\",e=new c(this,f)),\"string\"==typeof b&&e[b]())})}var c=function(a,b){this.init(\"popover\",a,b)};if(!a.fn.tooltip)throw new Error(\"Popover requires tooltip.js\");c.VERSION=\"3.3.5\",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:\"right\",trigger:\"click\",content:\"\",template:'

    '}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(\".popover-title\")[this.options.html?\"html\":\"text\"](b),a.find(\".popover-content\").children().detach().end()[this.options.html?\"string\"==typeof c?\"html\":\"append\":\"text\"](c),a.removeClass(\"fade top bottom left right in\"),a.find(\".popover-title\").html()||a.find(\".popover-title\").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr(\"data-content\")||(\"function\"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(\".arrow\")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){\"use strict\";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||\"\")+\" .nav li > a\",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on(\"scroll.bs.scrollspy\",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data(\"bs.scrollspy\"),f=\"object\"==typeof c&&c;e||d.data(\"bs.scrollspy\",e=new b(this,f)),\"string\"==typeof c&&e[c]()})}b.VERSION=\"3.3.5\",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c=\"offset\",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c=\"position\",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data(\"target\")||b.attr(\"href\"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(\":visible\")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active\").removeClass(\"active\").end().find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!1),b.addClass(\"active\").find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!0),h?(b[0].offsetWidth,b.addClass(\"in\")):b.removeClass(\"fade\"),b.parent(\".dropdown-menu\").length&&b.closest(\"li.dropdown\").addClass(\"active\").end().find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!0),e&&e()}var g=d.find(\"> .active\"),h=e&&a.support.transition&&(g.length&&g.hasClass(\"fade\")||!!d.find(\"> .fade\").length);g.length&&h?g.one(\"bsTransitionEnd\",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass(\"in\")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),\"show\")};a(document).on(\"click.bs.tab.data-api\",'[data-toggle=\"tab\"]',e).on(\"click.bs.tab.data-api\",'[data-toggle=\"pill\"]',e)}(jQuery),+function(a){\"use strict\";function b(b){return this.each(function(){var d=a(this),e=d.data(\"bs.affix\"),f=\"object\"==typeof b&&b;e||d.data(\"bs.affix\",e=new c(this,f)),\"string\"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on(\"scroll.bs.affix.data-api\",a.proxy(this.checkPosition,this)).on(\"click.bs.affix.data-api\",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION=\"3.3.5\",c.RESET=\"affix affix-top affix-bottom\",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&\"top\"==this.affixed)return c>e?\"top\":!1;if(\"bottom\"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:\"bottom\":a-d>=e+g?!1:\"bottom\";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?\"top\":null!=d&&i+j>=a-d?\"bottom\":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass(\"affix\");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(\":visible\")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());\"object\"!=typeof d&&(f=e=d),\"function\"==typeof e&&(e=d.top(this.$element)),\"function\"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css(\"top\",\"\");var i=\"affix\"+(h?\"-\"+h:\"\"),j=a.Event(i+\".bs.affix\");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin=\"bottom\"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace(\"affix\",\"affixed\")+\".bs.affix\")}\"bottom\"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on(\"load\",function(){a('[data-spy=\"affix\"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);PK\x07\x08^\xbfIn\xd0\x8f\x00\x00\xd0\x8f\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00J\x8f\xc3H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00js/vendor/jquery-2.1.4.min.js/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */\n!function(a,b){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error(\"jQuery requires a window with a document\");return b(a)}:b(a)}(\"undefined\"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m=\"2.1.4\",n=function(a,b){return new n.fn.init(a,b)},o=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,p=/^-ms-/,q=/-([\\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:\"\",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for(\"boolean\"==typeof g&&(j=g,g=arguments[h]||{},h++),\"object\"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:\"jQuery\"+(m+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return\"function\"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return\"object\"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,\"isPrototypeOf\")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+\"\":\"object\"==typeof a||\"function\"==typeof a?h[i.call(a)]||\"object\":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf(\"use strict\")?(b=l.createElement(\"script\"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,\"ms-\").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?\"\":(a+\"\").replace(o,\"\")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,\"string\"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return\"string\"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(a,b){h[\"[object \"+b+\"]\"]=b.toLowerCase()});function s(a){var b=\"length\"in a&&a.length,c=n.type(a);return\"function\"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:\"array\"===c||0===b||\"number\"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=\"sizzle\"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",L=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",M=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",N=M.replace(\"w\",\"w#\"),O=\"\\\\[\"+L+\"*(\"+M+\")(?:\"+L+\"*([*^$|!~]?=)\"+L+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+N+\"))|)\"+L+\"*\\\\]\",P=\":(\"+M+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+O+\")*)|.*)\\\\)|)\",Q=new RegExp(L+\"+\",\"g\"),R=new RegExp(\"^\"+L+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+L+\"+$\",\"g\"),S=new RegExp(\"^\"+L+\"*,\"+L+\"*\"),T=new RegExp(\"^\"+L+\"*([>+~]|\"+L+\")\"+L+\"*\"),U=new RegExp(\"=\"+L+\"*([^\\\\]'\\\"]*?)\"+L+\"*\\\\]\",\"g\"),V=new RegExp(P),W=new RegExp(\"^\"+N+\"$\"),X={ID:new RegExp(\"^#(\"+M+\")\"),CLASS:new RegExp(\"^\\\\.(\"+M+\")\"),TAG:new RegExp(\"^(\"+M.replace(\"w\",\"w*\")+\")\"),ATTR:new RegExp(\"^\"+O),PSEUDO:new RegExp(\"^\"+P),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+L+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+L+\"*(?:([+-]|)\"+L+\"*(\\\\d+)|))\"+L+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+K+\")$\",\"i\"),needsContext:new RegExp(\"^\"+L+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+L+\"*((?:-\\\\d)?\\\\d*)\"+L+\"*\\\\)|)(?=[^-]|$)\",\"i\")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\\d$/i,$=/^[^{]+\\{\\s*\\[native \\w/,_=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,aa=/[+~]/,ba=/'|\\\\/g,ca=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+L+\"?|(\"+L+\")|.)\",\"ig\"),da=function(a,b,c){var d=\"0x\"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,\"string\"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&\"object\"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute(\"id\"))?s=r.replace(ba,\"\\\\$&\"):b.setAttribute(\"id\",s),s=\"[id='\"+s+\"'] \",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(\",\")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute(\"id\")}}}return i(a.replace(R,\"$1\"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+\" \")>d.cacheLength&&delete b[a.shift()],b[c+\" \"]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement(\"div\");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split(\"|\"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return\"input\"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return(\"input\"===c||\"button\"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&\"undefined\"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?\"HTML\"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener(\"unload\",ea,!1):e.attachEvent&&e.attachEvent(\"onunload\",ea)),p=!f(g),c.attributes=ja(function(a){return a.className=\"i\",!a.getAttribute(\"className\")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment(\"\")),!a.getElementsByTagName(\"*\").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(\"undefined\"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute(\"id\")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c=\"undefined\"!=typeof a.getAttributeNode&&a.getAttributeNode(\"id\");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return\"undefined\"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if(\"*\"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML=\"\",a.querySelectorAll(\"[msallowcapture^='']\").length&&q.push(\"[*^$]=\"+L+\"*(?:''|\\\"\\\")\"),a.querySelectorAll(\"[selected]\").length||q.push(\"\\\\[\"+L+\"*(?:value|\"+K+\")\"),a.querySelectorAll(\"[id~=\"+u+\"-]\").length||q.push(\"~=\"),a.querySelectorAll(\":checked\").length||q.push(\":checked\"),a.querySelectorAll(\"a#\"+u+\"+*\").length||q.push(\".#.+[+~]\")}),ja(function(a){var b=g.createElement(\"input\");b.setAttribute(\"type\",\"hidden\"),a.appendChild(b).setAttribute(\"name\",\"D\"),a.querySelectorAll(\"[name=d]\").length&&q.push(\"name\"+L+\"*[*^$|!~]?=\"),a.querySelectorAll(\":enabled\").length||q.push(\":enabled\",\":disabled\"),a.querySelectorAll(\"*,:x\"),q.push(\",.*:\")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,\"div\"),s.call(a,\"[s!='']:x\"),r.push(\"!=\",P)}),q=q.length&&new RegExp(q.join(\"|\")),r=r.length&&new RegExp(r.join(\"|\")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,\"='$1']\"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error(\"Syntax error, unrecognized expression: \"+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c=\"\",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if(\"string\"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||\"\").replace(ca,da),\"~=\"===a[2]&&(a[3]=\" \"+a[3]+\" \"),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),\"nth\"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*(\"even\"===a[3]||\"odd\"===a[3])),a[5]=+(a[7]+a[8]||\"odd\"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||\"\":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(\")\",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return\"*\"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+\" \"];return b||(b=new RegExp(\"(^|\"+L+\")\"+a+\"(\"+L+\"|$)\"))&&y(a,function(a){return b.test(\"string\"==typeof a.className&&a.className||\"undefined\"!=typeof a.getAttribute&&a.getAttribute(\"class\")||\"\")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?\"!=\"===b:b?(e+=\"\",\"=\"===b?e===c:\"!=\"===b?e!==c:\"^=\"===b?c&&0===e.indexOf(c):\"*=\"===b?c&&e.indexOf(c)>-1:\"$=\"===b?c&&e.slice(-c.length)===c:\"~=\"===b?(\" \"+e.replace(Q,\" \")+\" \").indexOf(c)>-1:\"|=\"===b?e===c||e.slice(0,c.length+1)===c+\"-\":!1):!0}},CHILD:function(a,b,c,d,e){var f=\"nth\"!==a.slice(0,3),g=\"last\"!==a.slice(-4),h=\"of-type\"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?\"nextSibling\":\"previousSibling\",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p=\"only\"===a&&!o&&\"nextSibling\"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error(\"unsupported pseudo: \"+a);return e[u]?e(b):e.length>1?(c=[a,a,\"\",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,\"$1\"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||\"\")||ga.error(\"unsupported lang: \"+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute(\"xml:lang\")||b.getAttribute(\"lang\"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+\"-\");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&!!a.checked||\"option\"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&\"button\"===a.type||\"button\"===b},text:function(a){var b;return\"input\"===a.nodeName.toLowerCase()&&\"text\"===a.type&&(null==(b=a.getAttribute(\"type\"))||\"text\"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&\"parentNode\"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||\"*\",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[\" \"],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:\" \"===a[i-2].type?\"*\":\"\"})).replace(R,\"$1\"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q=\"0\",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG(\"*\",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+\" \"];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n=\"function\"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&\"ID\"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split(\"\").sort(B).join(\"\")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement(\"div\"))}),ja(function(a){return a.innerHTML=\"\",\"#\"===a.firstChild.getAttribute(\"href\")})||ka(\"type|href|height|width\",function(a,b,c){return c?void 0:a.getAttribute(b,\"type\"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML=\"\",a.firstChild.setAttribute(\"value\",\"\"),\"\"===a.firstChild.getAttribute(\"value\")})||ka(\"value\",function(a,b,c){return c||\"input\"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute(\"disabled\")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[\":\"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,w=/^.[^:#\\[\\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if(\"string\"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=\":not(\"+a+\")\"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if(\"string\"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+\" \"+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,\"string\"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if(\"string\"==typeof a){if(c=\"<\"===a[0]&&\">\"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?\"undefined\"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||\"string\"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?\"string\"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,\"parentNode\")},parentsUntil:function(a,b,c){return n.dir(a,\"parentNode\",c)},next:function(a){return D(a,\"nextSibling\")},prev:function(a){return D(a,\"previousSibling\")},nextAll:function(a){return n.dir(a,\"nextSibling\")},prevAll:function(a){return n.dir(a,\"previousSibling\")},nextUntil:function(a,b,c){return n.dir(a,\"nextSibling\",c)},prevUntil:function(a,b,c){return n.dir(a,\"previousSibling\",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return\"Until\"!==a.slice(-5)&&(d=c),d&&\"string\"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a=\"string\"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);\"function\"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&\"string\"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[[\"resolve\",\"done\",n.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",n.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",n.Callbacks(\"memory\")]],c=\"pending\",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+\"With\"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+\"With\"](this===e?d:this,arguments),this},e[f[0]+\"With\"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler(\"ready\"),n(l).off(\"ready\"))))}});function I(){l.removeEventListener(\"DOMContentLoaded\",I,!1),a.removeEventListener(\"load\",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),\"complete\"===l.readyState?setTimeout(n.ready):(l.addEventListener(\"DOMContentLoaded\",I,!1),a.addEventListener(\"load\",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if(\"object\"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if(\"string\"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&\"string\"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d=\"data-\"+b.replace(O,\"-$1\").toLowerCase(),c=a.getAttribute(d),\"string\"==typeof c){try{c=\"true\"===c?!0:\"false\"===c?!1:\"null\"===c?null:+c+\"\"===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){\nreturn M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,\"hasDataAttrs\"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf(\"data-\")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,\"hasDataAttrs\",!0)}return e}return\"object\"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf(\"-\")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||\"fx\")+\"queue\",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||\"fx\";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};\"inprogress\"===e&&(e=c.shift(),d--),e&&(\"fx\"===b&&c.unshift(\"inprogress\"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+\"queueHooks\";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks(\"once memory\").add(function(){L.remove(a,[b+\"queue\",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return\"string\"!=typeof a&&(b=a,a=\"fx\",c--),arguments.lengthx\",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U=\"undefined\";k.focusinBubbles=\"onfocusin\"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||\"\").match(E)||[\"\"],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||\"\").split(\".\").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(\".\")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||\"\").match(E)||[\"\"],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||\"\").split(\".\").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp(\"(^|\\\\.)\"+p.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&(\"**\"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,\"events\"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,\"type\")?b.type:b,r=j.call(b,\"namespace\")?b.namespace.split(\".\"):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(\".\")>=0&&(r=q.split(\".\"),q=r.shift(),r.sort()),k=q.indexOf(\":\")<0&&\"on\"+q,b=b[n.expando]?b:new n.Event(q,\"object\"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join(\".\"),b.namespace_re=b.namespace?new RegExp(\"(^|\\\\.)\"+r.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,\"events\")||{})[b.type]&&L.get(g,\"handle\"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,\"events\")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||\"click\"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||\"click\"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+\" \",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\\/>/gi,ba=/<([\\w:]+)/,ca=/<|&#?\\w+;/,da=/<(?:script|style|link)/i,ea=/checked\\s*(?:[^=]|=\\s*.checked.)/i,fa=/^$|\\/(?:java|ecma)script/i,ga=/^true\\/(.*)/,ha=/^\\s*\\s*$/g,ia={option:[1,\"\"],thead:[1,\"\",\"
    \"],col:[2,\"\",\"
    \"],tr:[2,\"\",\"
    \"],td:[3,\"\",\"
    \"],_default:[0,\"\",\"\"]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,\"table\")&&n.nodeName(11!==b.nodeType?b:b.firstChild,\"tr\")?a.getElementsByTagName(\"tbody\")[0]||a.appendChild(a.ownerDocument.createElement(\"tbody\")):a}function ka(a){return a.type=(null!==a.getAttribute(\"type\"))+\"/\"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute(\"type\"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],\"globalEval\",!b||L.get(b[c],\"globalEval\"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||\"*\"):a.querySelectorAll?a.querySelectorAll(b||\"*\"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();\"input\"===c&&T.test(a.type)?b.checked=a.checked:(\"input\"===c||\"textarea\"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,\"script\"),g.length>0&&ma(g,!i&&oa(a,\"script\")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if(\"object\"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement(\"div\")),g=(ba.exec(e)||[\"\",\"\"])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,\"<$1>\")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=\"\"}else l.push(b.createTextNode(e));k.textContent=\"\",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),\"script\"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||\"\")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,\"script\")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent=\"\");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if(\"string\"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||[\"\",\"\"])[1].toLowerCase()]){a=a.replace(aa,\"<$1>\");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&\"string\"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,\"script\"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,\"script\"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||\"\")&&!L.access(h,\"globalEval\")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,\"\")))}return this}}),n.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],\"display\");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),\"none\"!==c&&c||(qa=(qa||n(\"