diff --git a/.gitignore b/.gitignore index 6855eb8..4b87d43 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,6 @@ /demo/tmp .vscode -main .DS_Store .swp .release diff --git a/.wtc.yaml b/.wtc.yaml index 215573f..233d2cf 100644 --- a/.wtc.yaml +++ b/.wtc.yaml @@ -7,7 +7,7 @@ rules: - name: run match: \.go$ ignore: web|examples|docs|_test\.go$ - command: go run main.go serv + command: go run cmd/main.go serv - name: test match: _test\.go$ command: go test -cover {PKG} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3930588..e95e163 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # stage: 1 FROM node:10 as react-build WORKDIR /web -COPY web/ ./ +COPY /cmd/internal/serv/web/ ./ RUN yarn RUN yarn build @@ -22,8 +22,8 @@ RUN chmod 755 /usr/local/bin/sops WORKDIR /app COPY . /app -RUN mkdir -p /app/web/build -COPY --from=react-build /web/build/ ./web/build/ +RUN mkdir -p /app/cmd/internal/serv/web/build +COPY --from=react-build /web/build/ ./cmd/internal/serv/web/build RUN go mod vendor RUN make build @@ -41,7 +41,7 @@ RUN mkdir -p /config COPY --from=go-build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=go-build /app/config/* /config/ COPY --from=go-build /app/super-graph . -COPY --from=go-build /app/scripts/start.sh . +COPY --from=go-build /app/cmd/scripts/start.sh . COPY --from=go-build /usr/local/bin/sops . RUN chmod +x /super-graph diff --git a/Makefile b/Makefile index 9ff2273..7300af9 100644 --- a/Makefile +++ b/Makefile @@ -28,14 +28,14 @@ BIN_DIR := $(GOPATH)/bin GORICE := $(BIN_DIR)/rice GOLANGCILINT := $(BIN_DIR)/golangci-lint GITCHGLOG := $(BIN_DIR)/git-chglog -WEB_BUILD_DIR := ./web/build/manifest.json +WEB_BUILD_DIR := ./cmd/internal/serv/web/build/manifest.json $(GORICE): @GO111MODULE=off go get -u github.com/GeertJohan/go.rice/rice $(WEB_BUILD_DIR): - @echo "First install Yarn and create a build of the web UI found under ./web" - @echo "Command: cd web && yarn && yarn build" + @echo "First install Yarn and create a build of the web UI then re-run make install" + @echo "Run this command: yarn --cwd cmd/internal/serv/web/ build" @exit 1 $(GITCHGLOG): @@ -57,7 +57,7 @@ os = $(word 1, $@) $(PLATFORMS): lint test @mkdir -p release - @GOOS=$(os) GOARCH=amd64 go build $(BUILD_FLAGS) -o release/$(BINARY)-$(BUILD_VERSION)-$(os)-amd64 + @GOOS=$(os) GOARCH=amd64 go build $(BUILD_FLAGS) -o release/$(BINARY)-$(BUILD_VERSION)-$(os)-amd64 cmd/main.go release: windows linux darwin @@ -69,7 +69,7 @@ gen: $(GORICE) $(WEB_BUILD_DIR) @go generate ./... $(BINARY): clean - @go build $(BUILD_FLAGS) -o $(BINARY) + @go build $(BUILD_FLAGS) -o $(BINARY) cmd/main.go clean: @rm -f $(BINARY) @@ -81,7 +81,7 @@ install: gen @echo $(GOPATH) @echo "Commit Hash: `git rev-parse HEAD`" @echo "Old Hash: `shasum $(GOPATH)/bin/$(BINARY) 2>/dev/null | cut -c -32`" - @go install $(BUILD_FLAGS) + @go install $(BUILD_FLAGS) cmd @echo "New Hash:" `shasum $(GOPATH)/bin/$(BINARY) 2>/dev/null | cut -c -32` uninstall: clean diff --git a/serv/.gitignore b/cmd/internal/serv/.gitignore similarity index 100% rename from serv/.gitignore rename to cmd/internal/serv/.gitignore diff --git a/serv/actions.go b/cmd/internal/serv/actions.go similarity index 70% rename from serv/actions.go rename to cmd/internal/serv/actions.go index 54e6065..6fb5651 100644 --- a/serv/actions.go +++ b/cmd/internal/serv/actions.go @@ -3,11 +3,13 @@ package serv import ( "fmt" "net/http" + + "github.com/dosco/super-graph/config" ) type actionFn func(w http.ResponseWriter, r *http.Request) error -func newAction(a configAction) (http.Handler, error) { +func newAction(a *config.Action) (http.Handler, error) { var fn actionFn var err error @@ -23,17 +25,16 @@ func newAction(a configAction) (http.Handler, error) { httpFn := func(w http.ResponseWriter, r *http.Request) { if err := fn(w, r); err != nil { - errlog.Error().Err(err).Send() - errorResp(w, err) + renderErr(w, err, nil) } } return http.HandlerFunc(httpFn), nil } -func newSQLAction(a configAction) (actionFn, error) { +func newSQLAction(a *config.Action) (actionFn, error) { fn := func(w http.ResponseWriter, r *http.Request) error { - _, err := db.Exec(r.Context(), a.SQL) + _, err := db.ExecContext(r.Context(), a.SQL) return err } diff --git a/serv/cmd.go b/cmd/internal/serv/cmd.go similarity index 78% rename from serv/cmd.go rename to cmd/internal/serv/cmd.go index ba8f8cd..4c45a13 100644 --- a/serv/cmd.go +++ b/cmd/internal/serv/cmd.go @@ -1,17 +1,17 @@ package serv import ( + "database/sql" "fmt" + _log "log" + "os" "runtime" "strings" - "github.com/dosco/super-graph/allow" - "github.com/dosco/super-graph/psql" - "github.com/dosco/super-graph/qcode" - "github.com/jackc/pgx/v4/pgxpool" - "github.com/rs/zerolog" + "github.com/dosco/super-graph/config" "github.com/spf13/cobra" "github.com/spf13/viper" + "go.uber.org/zap" ) //go:generate rice embed-go @@ -29,21 +29,17 @@ var ( ) var ( - logger zerolog.Logger // logger for everything but errors - errlog zerolog.Logger // logger for errors includes line numbers - conf *config // parsed config - confPath string // path to the config file - db *pgxpool.Pool // database connection pool - schema *psql.DBSchema // database tables, columns and relationships - allowList *allow.List // allow.list is contains queries allowed in production - qcompile *qcode.Compiler // qcode compiler - pcompile *psql.Compiler // postgres sql compiler - secretKey [32]byte // encryption key - internalKey [32]byte // encryption key used for internal needs + log *_log.Logger // logger + zlog *zap.Logger // fast logger + conf *config.Config // parsed config + confPath string // path to the config file + db *sql.DB // database connection pool + secretKey [32]byte // encryption key ) func Cmd() { - initLog() + log = _log.New(os.Stdout, "", 0) + zlog = zap.NewExample() rootCmd := &cobra.Command{ Use: "super-graph", @@ -149,11 +145,11 @@ e.g. db:migrate -+1 Run: cmdVersion, }) - rootCmd.Flags().StringVar(&confPath, + rootCmd.PersistentFlags().StringVar(&confPath, "path", "./config", "path to config files") if err := rootCmd.Execute(); err != nil { - errlog.Fatal().Err(err).Send() + log.Fatalf("ERR %s", err) } } diff --git a/cmd/internal/serv/cmd_conf.go b/cmd/internal/serv/cmd_conf.go new file mode 100644 index 0000000..7e75aaa --- /dev/null +++ b/cmd/internal/serv/cmd_conf.go @@ -0,0 +1,29 @@ +package serv + +import ( + "fmt" + "os" + + "github.com/dosco/super-graph/config" + "github.com/spf13/cobra" +) + +func cmdConfDump(cmd *cobra.Command, args []string) { + if len(args) != 1 { + cmd.Help() //nolint: errcheck + os.Exit(1) + } + + fname := fmt.Sprintf("%s.%s", config.GetConfigName(), args[0]) + + conf, err := initConf() + if err != nil { + log.Fatalf("ERR failed to read config: %s", err) + } + + if err := conf.WriteConfigAs(fname); err != nil { + log.Fatalf("ERR failed to write config: %s", err) + } + + log.Printf("INF config dumped to ./%s", fname) +} diff --git a/serv/cmd_migrate.go b/cmd/internal/serv/cmd_migrate.go similarity index 66% rename from serv/cmd_migrate.go rename to cmd/internal/serv/cmd_migrate.go index fdeae85..eebac77 100644 --- a/serv/cmd_migrate.go +++ b/cmd/internal/serv/cmd_migrate.go @@ -1,7 +1,6 @@ package serv import ( - "context" "fmt" "os" "path" @@ -10,7 +9,7 @@ import ( "strings" "time" - "github.com/dosco/super-graph/migrate" + "github.com/dosco/super-graph/cmd/internal/serv/internal/migrate" "github.com/spf13/cobra" ) @@ -27,7 +26,7 @@ func cmdDBSetup(cmd *cobra.Command, args []string) { cmdDBCreate(cmd, []string{}) cmdDBMigrate(cmd, []string{"up"}) - sfile := path.Join(confPath, conf.SeedFile) + sfile := path.Join(conf.ConfigPathUsed(), conf.SeedFile) _, err := os.Stat(sfile) if err == nil { @@ -36,61 +35,59 @@ func cmdDBSetup(cmd *cobra.Command, args []string) { } if !os.IsNotExist(err) { - errlog.Fatal().Err(err).Msgf("unable to check if '%s' exists", sfile) + log.Fatalf("ERR unable to check if '%s' exists: %s", sfile, err) } - logger.Warn().Msgf("failed to read seed file '%s'", sfile) + log.Printf("WRN failed to read seed file '%s'", sfile) } func cmdDBReset(cmd *cobra.Command, args []string) { initConfOnce() if conf.Production { - errlog.Fatal().Msg("db:reset does not work in production") - return + log.Fatalln("ERR db:reset does not work in production") } + cmdDBDrop(cmd, []string{}) cmdDBSetup(cmd, []string{}) } func cmdDBCreate(cmd *cobra.Command, args []string) { initConfOnce() - ctx := context.Background() - conn, err := initDB(conf, false) + db, err := initDB(conf) if err != nil { - errlog.Fatal().Err(err).Msg("failed to connect to database") + log.Fatalf("ERR failed to connect to database: %s", err) } - defer conn.Close(ctx) + defer db.Close() sql := fmt.Sprintf(`CREATE DATABASE "%s"`, conf.DB.DBName) - _, err = conn.Exec(ctx, sql) + _, err = db.Exec(sql) if err != nil { - errlog.Fatal().Err(err).Msg("failed to create database") + log.Fatalf("ERR failed to create database: %s", err) } - logger.Info().Msgf("created database '%s'", conf.DB.DBName) + log.Printf("INF created database '%s'", conf.DB.DBName) } func cmdDBDrop(cmd *cobra.Command, args []string) { initConfOnce() - ctx := context.Background() - conn, err := initDB(conf, false) + db, err := initDB(conf) if err != nil { - errlog.Fatal().Err(err).Msg("failed to connect to database") + log.Fatalf("ERR failed to connect to database: %s", err) } - defer conn.Close(ctx) + defer db.Close() sql := fmt.Sprintf(`DROP DATABASE IF EXISTS "%s"`, conf.DB.DBName) - _, err = conn.Exec(ctx, sql) + _, err = db.Exec(sql) if err != nil { - errlog.Fatal().Err(err).Msg("failed to create database") + log.Fatalf("ERR failed to drop database: %s", err) } - logger.Info().Msgf("dropped database '%s'", conf.DB.DBName) + log.Printf("INF dropped database '%s'", conf.DB.DBName) } func cmdDBNew(cmd *cobra.Command, args []string) { @@ -104,8 +101,7 @@ func cmdDBNew(cmd *cobra.Command, args []string) { m, err := migrate.FindMigrations(conf.MigrationsPath) if err != nil { - fmt.Fprintf(os.Stderr, "Error loading migrations:\n %v\n", err) - os.Exit(1) + log.Fatalf("ERR error loading migrations: %s", err) } mname := fmt.Sprintf("%d_%s.sql", len(m), name) @@ -114,17 +110,16 @@ func cmdDBNew(cmd *cobra.Command, args []string) { mpath := filepath.Join(conf.MigrationsPath, mname) mfile, err := os.OpenFile(mpath, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0666) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + log.Fatalf("ERR %s", err) } defer mfile.Close() _, err = mfile.WriteString(newMigrationText) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + log.Fatalf("ERR %s", err) } - logger.Info().Msgf("created migration '%s'", mpath) + + log.Printf("INR created migration '%s'", mpath) } func cmdDBMigrate(cmd *cobra.Command, args []string) { @@ -136,30 +131,30 @@ func cmdDBMigrate(cmd *cobra.Command, args []string) { initConfOnce() dest := args[0] - conn, err := initDB(conf, true) + conn, err := initDB(conf) if err != nil { - errlog.Fatal().Err(err).Msg("failed to connect to database") + log.Fatalf("ERR failed to connect to database: %s", err) } - defer conn.Close(context.Background()) + defer conn.Close() m, err := migrate.NewMigrator(conn, "schema_version") if err != nil { - errlog.Fatal().Err(err).Msg("failed to initializing migrator") + log.Fatalf("ERR failed to initializing migrator: %s", err) } m.Data = getMigrationVars() - err = m.LoadMigrations(conf.MigrationsPath) + err = m.LoadMigrations(path.Join(conf.ConfigPathUsed(), conf.MigrationsPath)) if err != nil { - errlog.Fatal().Err(err).Msg("failed to load migrations") + log.Fatalf("ERR failed to load migrations: %s", err) } if len(m.Migrations) == 0 { - errlog.Fatal().Msg("No migrations found") + log.Fatalf("ERR no migrations found") } m.OnStart = func(sequence int32, name, direction, sql string) { - logger.Info().Msgf("%s executing %s %s\n%s\n\n", + log.Printf("INF %s executing %s %s\n%s\n\n", time.Now().Format("2006-01-02 15:04:05"), name, direction, sql) } @@ -174,7 +169,7 @@ func cmdDBMigrate(cmd *cobra.Command, args []string) { var n int64 n, err = strconv.ParseInt(d, 10, 32) if err != nil { - errlog.Fatal().Err(err).Msg("invalid destination") + log.Fatalf("ERR invalid destination: %s", err) } return int32(n) } @@ -203,58 +198,56 @@ func cmdDBMigrate(cmd *cobra.Command, args []string) { } if err != nil { - logger.Fatal().Err(err).Send() + log.Fatalf("ERR %s", err) // if err, ok := err.(m.MigrationPgError); ok { // if err.Detail != "" { - // info.Err(err).Msg(err.Detail) + // log.Fatalf("ERR %s", err.Detail) // } // if err.Position != 0 { // ele, err := ExtractErrorLine(err.Sql, int(err.Position)) // if err != nil { - // errlog.Fatal().Err(err).Send() + // log.Fatalf("ERR %s", err) // } - // prefix := fmt.Sprintf() - // logger.Info().Msgf("line %d, %s%s", ele.LineNum, prefix, ele.Text) + // log.Fatalf("INF line %d, %s%s", ele.LineNum, ele.Text) // } + // } - // os.Exit(1) } - logger.Info().Msg("migration done") - + log.Println("INF migration done") } func cmdDBStatus(cmd *cobra.Command, args []string) { initConfOnce() - conn, err := initDB(conf, true) + db, err := initDB(conf) if err != nil { - errlog.Fatal().Err(err).Msg("failed to connect to database") + log.Fatalf("ERR failed to connect to database: %s", err) } - defer conn.Close(context.Background()) + defer db.Close() - m, err := migrate.NewMigrator(conn, "schema_version") + m, err := migrate.NewMigrator(db, "schema_version") if err != nil { - errlog.Fatal().Err(err).Msg("failed to initialize migrator") + log.Fatalf("ERR failed to initialize migrator: %s", err) } m.Data = getMigrationVars() err = m.LoadMigrations(conf.MigrationsPath) if err != nil { - errlog.Fatal().Err(err).Msg("failed to load migrations") + log.Fatalf("ERR failed to load migrations: %s", err) } if len(m.Migrations) == 0 { - errlog.Fatal().Msg("no migrations found") + log.Fatalf("ERR no migrations found") } mver, err := m.GetCurrentVersion() if err != nil { - errlog.Fatal().Err(err).Msg("failed to retrieve migration") + log.Fatalf("ERR failed to retrieve migration: %s", err) } var status string @@ -265,10 +258,8 @@ func cmdDBStatus(cmd *cobra.Command, args []string) { status = "migration(s) pending" } - fmt.Println("status: ", status) - fmt.Printf("version: %d of %d\n", mver, len(m.Migrations)) - fmt.Println("host: ", conf.DB.Host) - fmt.Println("database:", conf.DB.DBName) + log.Printf("INF status: %s, version: %d of %d, host: %s, database: %s", + status, mver, len(m.Migrations), conf.DB.Host, conf.DB.DBName) } type ErrorLineExtract struct { @@ -315,9 +306,12 @@ func getMigrationVars() map[string]interface{} { func initConfOnce() { var err error - if conf == nil { - if conf, err = initConf(); err != nil { - errlog.Fatal().Err(err).Msg("failed to read config") - } + if conf != nil { + return + } + + conf, err = initConf() + if err != nil { + log.Fatalf("ERR failed to read config: %s", err) } } diff --git a/serv/cmd_new.go b/cmd/internal/serv/cmd_new.go similarity index 89% rename from serv/cmd_new.go rename to cmd/internal/serv/cmd_new.go index b2be52b..3557db7 100644 --- a/serv/cmd_new.go +++ b/cmd/internal/serv/cmd_new.go @@ -98,7 +98,7 @@ func cmdNew(cmd *cobra.Command, args []string) { } }) - logger.Info().Msgf("app '%s' initialized", name) + log.Printf("INR app '%s' initialized", name) } type Templ struct { @@ -107,7 +107,7 @@ type Templ struct { } func newTempl(data map[string]string) *Templ { - return &Templ{rice.MustFindBox("../tmpl"), data} + return &Templ{rice.MustFindBox("./tmpl"), data} } func (t *Templ) get(name string) ([]byte, error) { @@ -133,18 +133,18 @@ func ifNotExists(filePath string, doFn func(string) error) { _, err := os.Stat(filePath) if err == nil { - logger.Info().Err(err).Msgf("create skipped '%s' exists", filePath) + log.Printf("ERR create skipped '%s' exists", filePath) return } if !os.IsNotExist(err) { - errlog.Fatal().Err(err).Msgf("unable to check if '%s' exists", filePath) + log.Fatalf("ERR unable to check if '%s' exists", filePath) } err = doFn(filePath) if err != nil { - errlog.Fatal().Err(err).Msgf("unable to create '%s'", filePath) + log.Fatalf("ERR unable to create '%s'", filePath) } - logger.Info().Msgf("created '%s'", filePath) + log.Printf("INR created '%s'", filePath) } diff --git a/serv/cmd_seed.go b/cmd/internal/serv/cmd_seed.go similarity index 78% rename from serv/cmd_seed.go rename to cmd/internal/serv/cmd_seed.go index b63a5f7..c2d160b 100644 --- a/serv/cmd_seed.go +++ b/cmd/internal/serv/cmd_seed.go @@ -1,7 +1,6 @@ package serv import ( - "bytes" "context" "encoding/csv" "encoding/json" @@ -16,37 +15,43 @@ import ( "github.com/brianvoe/gofakeit" "github.com/dop251/goja" - "github.com/jackc/pgx/v4" + "github.com/dosco/super-graph/core" "github.com/spf13/cobra" - "github.com/valyala/fasttemplate" ) func cmdDBSeed(cmd *cobra.Command, args []string) { var err error if conf, err = initConf(); err != nil { - errlog.Fatal().Err(err).Msg("failed to read config") + log.Fatalf("ERR failed to read config: %s", err) } conf.Production = false - db, err = initDBPool(conf) + db, err = initDB(conf) if err != nil { - errlog.Fatal().Err(err).Msg("failed to connect to database") + log.Fatalf("ERR failed to connect to database: %s", err) } - initCompiler() + sfile := path.Join(conf.ConfigPathUsed(), conf.SeedFile) - sfile := path.Join(confPath, conf.SeedFile) - - b, err := ioutil.ReadFile(path.Join(confPath, conf.SeedFile)) + b, err := ioutil.ReadFile(sfile) if err != nil { - errlog.Fatal().Err(err).Msgf("failed to read seed file '%s'", sfile) + log.Fatalf("ERR failed to read seed file %s: %s", sfile, err) + } + + sg, err = core.NewSuperGraph(conf, db) + if err != nil { + log.Fatalf("ERR failed to initialize Super Graph: %s", err) + } + + graphQLFn := func(query string, data interface{}, opt map[string]string) map[string]interface{} { + return graphQLFunc(sg, query, data, opt) } vm := goja.New() - vm.Set("graphql", graphQLFunc) - vm.Set("import_csv", importCSV) + vm.Set("graphql", graphQLFn) + //vm.Set("import_csv", importCSV) console := vm.NewObject() console.Set("log", logFunc) //nolint: errcheck @@ -58,77 +63,44 @@ func cmdDBSeed(cmd *cobra.Command, args []string) { _, err = vm.RunScript("seed.js", string(b)) if err != nil { - errlog.Fatal().Err(err).Msg("failed to execute script") + log.Fatalf("ERR failed to execute script: %s", err) } - logger.Info().Msg("seed script done") + log.Println("INF seed script done") } -//func runFunc(call goja.FunctionCall) { -func graphQLFunc(query string, data interface{}, opt map[string]string) map[string]interface{} { - vars, err := json.Marshal(data) - if err != nil { - errlog.Fatal().Err(err).Send() - } - - c := context.Background() +// func runFunc(call goja.FunctionCall) { +func graphQLFunc(sg *core.SuperGraph, query string, data interface{}, opt map[string]string) map[string]interface{} { + ct := context.Background() if v, ok := opt["user_id"]; ok && len(v) != 0 { - c = context.WithValue(c, userIDKey, v) + ct = context.WithValue(ct, core.UserIDKey, v) } - var role string + // var role string - if v, ok := opt["role"]; ok && len(v) != 0 { - role = v - } else { - role = "user" + // if v, ok := opt["role"]; ok && len(v) != 0 { + // role = v + // } else { + // role = "user" + // } + + var vars []byte + var err error + + if vars, err = json.Marshal(data); err != nil { + log.Fatalf("ERR %s", err) } - stmts, err := buildRoleStmt([]byte(query), vars, role) + res, err := sg.GraphQL(ct, query, vars) if err != nil { - errlog.Fatal().Err(err).Msg("graphql query failed") - } - st := stmts[0] - - buf := &bytes.Buffer{} - - t := fasttemplate.New(st.sql, openVar, closeVar) - _, err = t.ExecuteFunc(buf, argMap(c, vars)) - - if err != nil { - errlog.Fatal().Err(err).Send() - } - - finalSQL := buf.String() - - tx, err := db.Begin(c) - if err != nil { - errlog.Fatal().Err(err).Send() - } - defer tx.Rollback(c) //nolint: errcheck - - if conf.DB.SetUserID { - if err := setLocalUserID(c, tx); err != nil { - errlog.Fatal().Err(err).Send() - } - } - - var root []byte - - if err = tx.QueryRow(context.Background(), finalSQL).Scan(&root); err != nil { - errlog.Fatal().Err(err).Msg("sql query failed") - } - - if err := tx.Commit(c); err != nil { - errlog.Fatal().Err(err).Send() + log.Fatalf("ERR %s", err) } val := make(map[string]interface{}) - err = json.Unmarshal(root, &val) - if err != nil { - errlog.Fatal().Err(err).Send() + if err = json.Unmarshal(res.Data, &val); err != nil { + log.Fatalf("ERR %s", err) } return val @@ -203,36 +175,34 @@ func (c *csvSource) Err() error { return nil } -func importCSV(table, filename string) int64 { - if filename[0] != '/' { - filename = path.Join(confPath, filename) - } +// func importCSV(table, filename string) int64 { +// if filename[0] != '/' { +// filename = path.Join(conf.ConfigPathUsed(), filename) +// } - s, err := NewCSVSource(filename) - if err != nil { - errlog.Fatal().Err(err).Send() - } +// s, err := NewCSVSource(filename) +// if err != nil { +// log.Fatalf("ERR %s", err) +// } - var cols []string - colval, _ := s.Values() +// var cols []string +// colval, _ := s.Values() - for _, c := range colval { - cols = append(cols, c.(string)) - } +// for _, c := range colval { +// cols = append(cols, c.(string)) +// } - n, err := db.CopyFrom( - context.Background(), - pgx.Identifier{table}, - cols, - s) +// n, err := db.Exec(fmt.Sprintf("COPY %s FROM STDIN WITH "), +// cols, +// s) - if err != nil { - err = fmt.Errorf("%w (line no %d)", err, s.i) - errlog.Fatal().Err(err).Send() - } +// if err != nil { +// err = fmt.Errorf("%w (line no %d)", err, s.i) +// log.Fatalf("ERR %s", err) +// } - return n -} +// return n +// } //nolint: errcheck func logFunc(args ...interface{}) { diff --git a/cmd/internal/serv/cmd_serv.go b/cmd/internal/serv/cmd_serv.go new file mode 100644 index 0000000..7c8a3b7 --- /dev/null +++ b/cmd/internal/serv/cmd_serv.go @@ -0,0 +1,37 @@ +package serv + +import ( + "github.com/dosco/super-graph/core" + "github.com/spf13/cobra" +) + +var ( + sg *core.SuperGraph +) + +func cmdServ(cmd *cobra.Command, args []string) { + var err error + + conf, err = initConf() + if err != nil { + fatalInProd(err, "failed to read config") + } + + initWatcher() + + db, err = initDB(conf) + if err != nil { + fatalInProd(err, "failed to connect to database") + } + + // if conf != nil && db != nil { + // initResolvers() + // } + + sg, err = core.NewSuperGraph(conf, db) + if err != nil { + fatalInProd(err, "failed to initialize Super Graph") + } + + startHTTP() +} diff --git a/cmd/internal/serv/core.go b/cmd/internal/serv/core.go new file mode 100644 index 0000000..a0f044e --- /dev/null +++ b/cmd/internal/serv/core.go @@ -0,0 +1,7 @@ +package serv + +// func (c *coreContext) handleReq(w io.Writer, req *http.Request) error { + +// return nil + +// } diff --git a/qcode/corpus/001.gql b/cmd/internal/serv/corpus/001.gql similarity index 100% rename from qcode/corpus/001.gql rename to cmd/internal/serv/corpus/001.gql diff --git a/serv/fuzz.go b/cmd/internal/serv/fuzz.go similarity index 100% rename from serv/fuzz.go rename to cmd/internal/serv/fuzz.go diff --git a/serv/fuzz_test.go b/cmd/internal/serv/fuzz_test.go similarity index 100% rename from serv/fuzz_test.go rename to cmd/internal/serv/fuzz_test.go diff --git a/cmd/internal/serv/health.go b/cmd/internal/serv/health.go new file mode 100644 index 0000000..e1092fb --- /dev/null +++ b/cmd/internal/serv/health.go @@ -0,0 +1,25 @@ +package serv + +import ( + "context" + "net/http" +) + +var healthyResponse = []byte("All's Well") + +func health(w http.ResponseWriter, _ *http.Request) { + ct, cancel := context.WithTimeout(context.Background(), conf.DB.PingTimeout) + defer cancel() + + if err := db.PingContext(ct); err != nil { + log.Printf("ERR error pinging database: %s", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if _, err := w.Write(healthyResponse); err != nil { + log.Printf("ERR error writing healthy response: %s", err) + w.WriteHeader(http.StatusInternalServerError) + return + } +} diff --git a/cmd/internal/serv/http.go b/cmd/internal/serv/http.go new file mode 100644 index 0000000..a964c34 --- /dev/null +++ b/cmd/internal/serv/http.go @@ -0,0 +1,125 @@ +package serv + +import ( + "encoding/json" + "errors" + "io" + "io/ioutil" + "net/http" + "strings" + + "github.com/dosco/super-graph/cmd/internal/serv/internal/auth" + "github.com/dosco/super-graph/config" + "github.com/dosco/super-graph/core" + "github.com/rs/cors" + "go.uber.org/zap" +) + +const ( + maxReadBytes = 100000 // 100Kb + introspectionQuery = "IntrospectionQuery" +) + +var ( + errUnauthorized = errors.New("not authorized") +) + +type gqlReq struct { + OpName string `json:"operationName"` + Query string `json:"query"` + Vars json.RawMessage `json:"variables"` +} + +type errorResp struct { + Error error `json:"error"` +} + +func apiV1Handler() http.Handler { + h, err := auth.WithAuth(http.HandlerFunc(apiV1), &conf.Auth) + if err != nil { + log.Fatalf("ERR %s", err) + } + + if len(conf.AllowedOrigins) != 0 { + c := cors.New(cors.Options{ + AllowedOrigins: conf.AllowedOrigins, + AllowCredentials: true, + Debug: conf.DebugCORS, + }) + h = c.Handler(h) + } + + return h +} + +func apiV1(w http.ResponseWriter, r *http.Request) { + ct := r.Context() + + //nolint: errcheck + if conf.AuthFailBlock && !auth.IsAuth(ct) { + renderErr(w, errUnauthorized, nil) + return + } + + b, err := ioutil.ReadAll(io.LimitReader(r.Body, maxReadBytes)) + if err != nil { + renderErr(w, err, nil) + return + } + defer r.Body.Close() + + req := gqlReq{} + + err = json.Unmarshal(b, &req) + if err != nil { + renderErr(w, err, nil) + return + } + + if strings.EqualFold(req.OpName, introspectionQuery) { + introspect(w) + return + } + + res, err := sg.GraphQL(ct, req.Query, req.Vars) + + if conf.LogLevel() >= config.LogLevelDebug { + log.Printf("DBG query:\n%s\nsql:\n%s", req.Query, res.SQL()) + } + + if err != nil { + renderErr(w, err, res) + return + } + + json.NewEncoder(w).Encode(res) + + if conf.LogLevel() >= config.LogLevelInfo { + zlog.Info("success", + zap.String("op", res.Operation()), + zap.String("name", res.QueryName()), + zap.String("role", res.Role()), + ) + } +} + +//nolint: errcheck +func renderErr(w http.ResponseWriter, err error, res *core.Result) { + if err == errUnauthorized { + w.WriteHeader(http.StatusUnauthorized) + } + + json.NewEncoder(w).Encode(&errorResp{err}) + + if conf.LogLevel() >= config.LogLevelError { + if res != nil { + zlog.Error(err.Error(), + zap.String("op", res.Operation()), + zap.String("name", res.QueryName()), + zap.String("role", res.Role()), + ) + } else { + zlog.Error(err.Error()) + } + } +} diff --git a/cmd/internal/serv/init.go b/cmd/internal/serv/init.go new file mode 100644 index 0000000..db1c75c --- /dev/null +++ b/cmd/internal/serv/init.go @@ -0,0 +1,88 @@ +package serv + +import ( + "database/sql" + "fmt" + "time" + + "github.com/dosco/super-graph/config" + _ "github.com/jackc/pgx/v4/stdlib" +) + +func initConf() (*config.Config, error) { + return config.NewConfigWithLogger(confPath, log) +} + +func initDB(c *config.Config) (*sql.DB, error) { + var db *sql.DB + var err error + + cs := fmt.Sprintf("postgres://%s:%s@%s:%d/%s", + c.DB.User, c.DB.Password, + c.DB.Host, c.DB.Port, c.DB.DBName) + + for i := 1; i < 10; i++ { + db, err = sql.Open("pgx", cs) + if err == nil { + break + } + time.Sleep(time.Duration(i*100) * time.Millisecond) + } + + if err != nil { + return nil, err + } + + return db, nil + + // config, _ := pgxpool.ParseConfig("") + // config.ConnConfig.Host = c.DB.Host + // config.ConnConfig.Port = c.DB.Port + // config.ConnConfig.Database = c.DB.DBName + // config.ConnConfig.User = c.DB.User + // config.ConnConfig.Password = c.DB.Password + // config.ConnConfig.RuntimeParams = map[string]string{ + // "application_name": c.AppName, + // "search_path": c.DB.Schema, + // } + + // switch c.LogLevel { + // case "debug": + // config.ConnConfig.LogLevel = pgx.LogLevelDebug + // case "info": + // config.ConnConfig.LogLevel = pgx.LogLevelInfo + // case "warn": + // config.ConnConfig.LogLevel = pgx.LogLevelWarn + // case "error": + // config.ConnConfig.LogLevel = pgx.LogLevelError + // default: + // config.ConnConfig.LogLevel = pgx.LogLevelNone + // } + + // config.ConnConfig.Logger = NewSQLLogger(logger) + + // // if c.DB.MaxRetries != 0 { + // // opt.MaxRetries = c.DB.MaxRetries + // // } + + // if c.DB.PoolSize != 0 { + // config.MaxConns = conf.DB.PoolSize + // } + + // var db *pgxpool.Pool + // var err error + + // for i := 1; i < 10; i++ { + // db, err = pgxpool.ConnectConfig(context.Background(), config) + // if err == nil { + // break + // } + // time.Sleep(time.Duration(i*100) * time.Millisecond) + // } + + // if err != nil { + // return nil, err + // } + + // return db, nil +} diff --git a/cmd/internal/serv/internal/auth/auth.go b/cmd/internal/serv/internal/auth/auth.go new file mode 100644 index 0000000..1529838 --- /dev/null +++ b/cmd/internal/serv/internal/auth/auth.go @@ -0,0 +1,95 @@ +package auth + +import ( + "context" + "fmt" + "net/http" + + "github.com/dosco/super-graph/config" + "github.com/dosco/super-graph/core" +) + +func SimpleHandler(ac *config.Auth, next http.Handler) (http.HandlerFunc, error) { + return func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + userIDProvider := r.Header.Get("X-User-ID-Provider") + if len(userIDProvider) != 0 { + ctx = context.WithValue(ctx, core.UserIDProviderKey, userIDProvider) + } + + userID := r.Header.Get("X-User-ID") + if len(userID) != 0 { + ctx = context.WithValue(ctx, core.UserIDKey, userID) + } + + userRole := r.Header.Get("X-User-Role") + if len(userRole) != 0 { + ctx = context.WithValue(ctx, core.UserRoleKey, userRole) + } + + next.ServeHTTP(w, r.WithContext(ctx)) + }, nil +} + +func HeaderHandler(ac *config.Auth, next http.Handler) (http.HandlerFunc, error) { + hdr := ac.Header + + if len(hdr.Name) == 0 { + return nil, fmt.Errorf("auth '%s': no header.name defined", ac.Name) + } + + if !hdr.Exists && len(hdr.Value) == 0 { + return nil, fmt.Errorf("auth '%s': no header.value defined", ac.Name) + } + + return func(w http.ResponseWriter, r *http.Request) { + var fo1 bool + value := r.Header.Get(hdr.Name) + + switch { + case hdr.Exists: + fo1 = (len(value) == 0) + + default: + fo1 = (value != hdr.Value) + } + + if fo1 { + http.Error(w, "401 unauthorized", http.StatusUnauthorized) + return + } + + next.ServeHTTP(w, r) + }, nil +} + +func WithAuth(next http.Handler, ac *config.Auth) (http.Handler, error) { + var err error + + if ac.CredsInHeader { + next, err = SimpleHandler(ac, next) + } + + if err != nil { + return nil, err + } + + switch ac.Type { + case "rails": + return RailsHandler(ac, next) + + case "jwt": + return JwtHandler(ac, next) + + case "header": + return HeaderHandler(ac, next) + + } + + return next, nil +} + +func IsAuth(ct context.Context) bool { + return ct.Value(core.UserIDKey) != nil +} diff --git a/serv/auth_jwt.go b/cmd/internal/serv/internal/auth/jwt.go similarity index 72% rename from serv/auth_jwt.go rename to cmd/internal/serv/internal/auth/jwt.go index ac8fe88..8a7b16d 100644 --- a/serv/auth_jwt.go +++ b/cmd/internal/serv/internal/auth/jwt.go @@ -1,4 +1,4 @@ -package serv +package auth import ( "context" @@ -7,6 +7,8 @@ import ( "strings" jwt "github.com/dgrijalva/jwt-go" + "github.com/dosco/super-graph/config" + "github.com/dosco/super-graph/core" ) const ( @@ -14,18 +16,18 @@ const ( jwtAuth0 int = iota + 1 ) -func jwtHandler(authc configAuth, next http.Handler) http.HandlerFunc { +func JwtHandler(ac *config.Auth, next http.Handler) (http.HandlerFunc, error) { var key interface{} var jwtProvider int - cookie := authc.Cookie + cookie := ac.Cookie - if authc.JWT.Provider == "auth0" { + if ac.JWT.Provider == "auth0" { jwtProvider = jwtAuth0 } - secret := authc.JWT.Secret - publicKeyFile := authc.JWT.PubKeyFile + secret := ac.JWT.Secret + publicKeyFile := ac.JWT.PubKeyFile switch { case len(secret) != 0: @@ -34,10 +36,10 @@ func jwtHandler(authc configAuth, next http.Handler) http.HandlerFunc { case len(publicKeyFile) != 0: kd, err := ioutil.ReadFile(publicKeyFile) if err != nil { - errlog.Fatal().Err(err).Send() + return nil, err } - switch authc.JWT.PubKeyType { + switch ac.JWT.PubKeyType { case "ecdsa": key, err = jwt.ParseECPublicKeyFromPEM(kd) @@ -50,7 +52,7 @@ func jwtHandler(authc configAuth, next http.Handler) http.HandlerFunc { } if err != nil { - errlog.Fatal().Err(err).Send() + return nil, err } } @@ -88,11 +90,11 @@ func jwtHandler(authc configAuth, next http.Handler) http.HandlerFunc { if jwtProvider == jwtAuth0 { sub := strings.Split(claims.Subject, "|") if len(sub) != 2 { - ctx = context.WithValue(ctx, userIDProviderKey, sub[0]) - ctx = context.WithValue(ctx, userIDKey, sub[1]) + ctx = context.WithValue(ctx, core.UserIDProviderKey, sub[0]) + ctx = context.WithValue(ctx, core.UserIDKey, sub[1]) } } else { - ctx = context.WithValue(ctx, userIDKey, claims.Subject) + ctx = context.WithValue(ctx, core.UserIDKey, claims.Subject) } next.ServeHTTP(w, r.WithContext(ctx)) @@ -100,5 +102,5 @@ func jwtHandler(authc configAuth, next http.Handler) http.HandlerFunc { } next.ServeHTTP(w, r) - } + }, nil } diff --git a/serv/auth_rails.go b/cmd/internal/serv/internal/auth/rails.go similarity index 51% rename from serv/auth_rails.go rename to cmd/internal/serv/internal/auth/rails.go index be1cfba..98d3008 100644 --- a/serv/auth_rails.go +++ b/cmd/internal/serv/internal/auth/rails.go @@ -1,4 +1,4 @@ -package serv +package auth import ( "context" @@ -9,50 +9,54 @@ import ( "strings" "github.com/bradfitz/gomemcache/memcache" - "github.com/dosco/super-graph/rails" + "github.com/dosco/super-graph/config" + "github.com/dosco/super-graph/core" + "github.com/dosco/super-graph/cmd/internal/serv/internal/rails" "github.com/garyburd/redigo/redis" ) -func railsHandler(authc configAuth, next http.Handler) http.HandlerFunc { - ru := authc.Rails.URL +func RailsHandler(ac *config.Auth, next http.Handler) (http.HandlerFunc, error) { + ru := ac.Rails.URL if strings.HasPrefix(ru, "memcache:") { - return railsMemcacheHandler(authc, next) + return RailsMemcacheHandler(ac, next) } if strings.HasPrefix(ru, "redis:") { - return railsRedisHandler(authc, next) + return RailsRedisHandler(ac, next) } - return railsCookieHandler(authc, next) + return RailsCookieHandler(ac, next) } -func railsRedisHandler(authc configAuth, next http.Handler) http.HandlerFunc { - cookie := authc.Cookie +func RailsRedisHandler(ac *config.Auth, next http.Handler) (http.HandlerFunc, error) { + cookie := ac.Cookie + if len(cookie) == 0 { - errlog.Fatal().Msg("no auth.cookie defined") + return nil, fmt.Errorf("no auth.cookie defined") } - if len(authc.Rails.URL) == 0 { - errlog.Fatal().Msg("no auth.rails.url defined") + if len(ac.Rails.URL) == 0 { + return nil, fmt.Errorf("no auth.rails.url defined") } rp := &redis.Pool{ - MaxIdle: authc.Rails.MaxIdle, - MaxActive: authc.Rails.MaxActive, + MaxIdle: ac.Rails.MaxIdle, + MaxActive: ac.Rails.MaxActive, Dial: func() (redis.Conn, error) { - c, err := redis.DialURL(authc.Rails.URL) + c, err := redis.DialURL(ac.Rails.URL) if err != nil { - errlog.Fatal().Err(err).Send() + return nil, err } - pwd := authc.Rails.Password + pwd := ac.Rails.Password if len(pwd) != 0 { if _, err := c.Do("AUTH", pwd); err != nil { - errlog.Fatal().Err(err).Send() + return nil, err } } - return c, err + + return c, nil }, } @@ -76,24 +80,25 @@ func railsRedisHandler(authc configAuth, next http.Handler) http.HandlerFunc { return } - ctx := context.WithValue(r.Context(), userIDKey, userID) + ctx := context.WithValue(r.Context(), core.UserIDKey, userID) next.ServeHTTP(w, r.WithContext(ctx)) - } + }, nil } -func railsMemcacheHandler(authc configAuth, next http.Handler) http.HandlerFunc { - cookie := authc.Cookie +func RailsMemcacheHandler(ac *config.Auth, next http.Handler) (http.HandlerFunc, error) { + cookie := ac.Cookie + if len(cookie) == 0 { - errlog.Fatal().Msg("no auth.cookie defined") + return nil, fmt.Errorf("no auth.cookie defined") } - if len(authc.Rails.URL) == 0 { - errlog.Fatal().Msg("no auth.rails.url defined") + if len(ac.Rails.URL) == 0 { + return nil, fmt.Errorf("no auth.rails.url defined") } - rURL, err := url.Parse(authc.Rails.URL) + rURL, err := url.Parse(ac.Rails.URL) if err != nil { - errlog.Fatal().Err(err).Send() + return nil, err } mc := memcache.New(rURL.Host) @@ -118,49 +123,49 @@ func railsMemcacheHandler(authc configAuth, next http.Handler) http.HandlerFunc return } - ctx := context.WithValue(r.Context(), userIDKey, userID) + ctx := context.WithValue(r.Context(), core.UserIDKey, userID) next.ServeHTTP(w, r.WithContext(ctx)) - } + }, nil } -func railsCookieHandler(authc configAuth, next http.Handler) http.HandlerFunc { - cookie := authc.Cookie +func RailsCookieHandler(ac *config.Auth, next http.Handler) (http.HandlerFunc, error) { + cookie := ac.Cookie if len(cookie) == 0 { - errlog.Fatal().Msg("no auth.cookie defined") + return nil, fmt.Errorf("no auth.cookie defined") } - ra, err := railsAuth(authc) + ra, err := railsAuth(ac) if err != nil { - errlog.Fatal().Err(err).Send() + return nil, err } return func(w http.ResponseWriter, r *http.Request) { ck, err := r.Cookie(cookie) if err != nil || len(ck.Value) == 0 { - logger.Warn().Err(err).Msg("rails cookie missing") + // logger.Warn().Err(err).Msg("rails cookie missing") next.ServeHTTP(w, r) return } userID, err := ra.ParseCookie(ck.Value) if err != nil { - logger.Warn().Err(err).Msg("failed to parse rails cookie") + // logger.Warn().Err(err).Msg("failed to parse rails cookie") next.ServeHTTP(w, r) return } - ctx := context.WithValue(r.Context(), userIDKey, userID) + ctx := context.WithValue(r.Context(), core.UserIDKey, userID) next.ServeHTTP(w, r.WithContext(ctx)) - } + }, nil } -func railsAuth(authc configAuth) (*rails.Auth, error) { - secret := authc.Rails.SecretKeyBase +func railsAuth(ac *config.Auth) (*rails.Auth, error) { + secret := ac.Rails.SecretKeyBase if len(secret) == 0 { return nil, errors.New("no auth.rails.secret_key_base defined") } - version := authc.Rails.Version + version := ac.Rails.Version if len(version) == 0 { return nil, errors.New("no auth.rails.version defined") } @@ -170,16 +175,16 @@ func railsAuth(authc configAuth) (*rails.Auth, error) { return nil, err } - if len(authc.Rails.Salt) != 0 { - ra.Salt = authc.Rails.Salt + if len(ac.Rails.Salt) != 0 { + ra.Salt = ac.Rails.Salt } - if len(authc.Rails.SignSalt) != 0 { - ra.SignSalt = authc.Rails.SignSalt + if len(ac.Rails.SignSalt) != 0 { + ra.SignSalt = ac.Rails.SignSalt } - if len(authc.Rails.AuthSalt) != 0 { - ra.AuthSalt = authc.Rails.AuthSalt + if len(ac.Rails.AuthSalt) != 0 { + ra.AuthSalt = ac.Rails.AuthSalt } return ra, nil diff --git a/migrate/migrate.go b/cmd/internal/serv/internal/migrate/migrate.go similarity index 89% rename from migrate/migrate.go rename to cmd/internal/serv/internal/migrate/migrate.go index 09b4908..163a386 100644 --- a/migrate/migrate.go +++ b/cmd/internal/serv/internal/migrate/migrate.go @@ -3,6 +3,7 @@ package migrate import ( "bytes" "context" + "database/sql" "fmt" "io/ioutil" "os" @@ -12,7 +13,6 @@ import ( "strings" "text/template" - "github.com/jackc/pgx/v4" "github.com/pkg/errors" ) @@ -62,7 +62,7 @@ type MigratorOptions struct { } type Migrator struct { - conn *pgx.Conn + db *sql.DB versionTable string options *MigratorOptions Migrations []*Migration @@ -70,12 +70,12 @@ type Migrator struct { Data map[string]interface{} // Data available to use in migrations } -func NewMigrator(conn *pgx.Conn, versionTable string) (m *Migrator, err error) { - return NewMigratorEx(conn, versionTable, &MigratorOptions{MigratorFS: defaultMigratorFS{}}) +func NewMigrator(db *sql.DB, versionTable string) (m *Migrator, err error) { + return NewMigratorEx(db, versionTable, &MigratorOptions{MigratorFS: defaultMigratorFS{}}) } -func NewMigratorEx(conn *pgx.Conn, versionTable string, opts *MigratorOptions) (m *Migrator, err error) { - m = &Migrator{conn: conn, versionTable: versionTable, options: opts} +func NewMigratorEx(db *sql.DB, versionTable string, opts *MigratorOptions) (m *Migrator, err error) { + m = &Migrator{db: db, versionTable: versionTable, options: opts} err = m.ensureSchemaVersionTableExists() m.Migrations = make([]*Migration, 0) m.Data = make(map[string]interface{}) @@ -254,14 +254,13 @@ func (m *Migrator) Migrate() error { // MigrateTo migrates to targetVersion func (m *Migrator) MigrateTo(targetVersion int32) (err error) { - ctx := context.Background() // Lock to ensure multiple migrations cannot occur simultaneously lockNum := int64(9628173550095224) // arbitrary random number - if _, lockErr := m.conn.Exec(ctx, "select pg_try_advisory_lock($1)", lockNum); lockErr != nil { + if _, lockErr := m.db.Exec("select pg_try_advisory_lock($1)", lockNum); lockErr != nil { return lockErr } defer func() { - _, unlockErr := m.conn.Exec(ctx, "select pg_advisory_unlock($1)", lockNum) + _, unlockErr := m.db.Exec("select pg_advisory_unlock($1)", lockNum) if err == nil && unlockErr != nil { err = unlockErr } @@ -310,11 +309,11 @@ func (m *Migrator) MigrateTo(targetVersion int32) (err error) { ctx := context.Background() - tx, err := m.conn.Begin(ctx) + tx, err := m.db.BeginTx(ctx, nil) if err != nil { return err } - defer tx.Rollback(ctx) //nolint: errcheck + defer tx.Rollback() //nolint: errcheck // Fire on start callback if m.OnStart != nil { @@ -322,7 +321,7 @@ func (m *Migrator) MigrateTo(targetVersion int32) (err error) { } // Execute the migration - _, err = tx.Exec(ctx, sql) + _, err = tx.Exec(sql) if err != nil { // if err, ok := err.(pgx.PgError); ok { // return MigrationPgError{Sql: sql, PgError: err} @@ -336,12 +335,12 @@ func (m *Migrator) MigrateTo(targetVersion int32) (err error) { // } // Add one to the version - _, err = tx.Exec(ctx, "update "+m.versionTable+" set version=$1", sequence) + _, err = tx.Exec("update "+m.versionTable+" set version=$1", sequence) if err != nil { return err } - err = tx.Commit(ctx) + err = tx.Commit() if err != nil { return err } @@ -353,14 +352,13 @@ func (m *Migrator) MigrateTo(targetVersion int32) (err error) { } func (m *Migrator) GetCurrentVersion() (v int32, err error) { - err = m.conn.QueryRow(context.Background(), - "select version from "+m.versionTable).Scan(&v) + err = m.db.QueryRow("select version from " + m.versionTable).Scan(&v) return v, err } func (m *Migrator) ensureSchemaVersionTableExists() (err error) { - _, err = m.conn.Exec(context.Background(), fmt.Sprintf(` + _, err = m.db.Exec(fmt.Sprintf(` create table if not exists %s(version int4 not null); insert into %s(version) diff --git a/migrate/migrate_test.go b/cmd/internal/serv/internal/migrate/migrate_test.go similarity index 100% rename from migrate/migrate_test.go rename to cmd/internal/serv/internal/migrate/migrate_test.go diff --git a/migrate/testdata/duplicate/001_create_t1.sql b/cmd/internal/serv/internal/migrate/testdata/duplicate/001_create_t1.sql similarity index 100% rename from migrate/testdata/duplicate/001_create_t1.sql rename to cmd/internal/serv/internal/migrate/testdata/duplicate/001_create_t1.sql diff --git a/migrate/testdata/duplicate/002_create_t2.sql b/cmd/internal/serv/internal/migrate/testdata/duplicate/002_create_t2.sql similarity index 100% rename from migrate/testdata/duplicate/002_create_t2.sql rename to cmd/internal/serv/internal/migrate/testdata/duplicate/002_create_t2.sql diff --git a/migrate/testdata/duplicate/002_duplicate.sql b/cmd/internal/serv/internal/migrate/testdata/duplicate/002_duplicate.sql similarity index 100% rename from migrate/testdata/duplicate/002_duplicate.sql rename to cmd/internal/serv/internal/migrate/testdata/duplicate/002_duplicate.sql diff --git a/migrate/testdata/empty/.gitignore b/cmd/internal/serv/internal/migrate/testdata/empty/.gitignore similarity index 100% rename from migrate/testdata/empty/.gitignore rename to cmd/internal/serv/internal/migrate/testdata/empty/.gitignore diff --git a/migrate/testdata/gap/001_create_people.sql.example b/cmd/internal/serv/internal/migrate/testdata/gap/001_create_people.sql.example similarity index 100% rename from migrate/testdata/gap/001_create_people.sql.example rename to cmd/internal/serv/internal/migrate/testdata/gap/001_create_people.sql.example diff --git a/migrate/testdata/gap/001_create_t1.sql b/cmd/internal/serv/internal/migrate/testdata/gap/001_create_t1.sql similarity index 100% rename from migrate/testdata/gap/001_create_t1.sql rename to cmd/internal/serv/internal/migrate/testdata/gap/001_create_t1.sql diff --git a/migrate/testdata/gap/003_irreversible.sql b/cmd/internal/serv/internal/migrate/testdata/gap/003_irreversible.sql similarity index 100% rename from migrate/testdata/gap/003_irreversible.sql rename to cmd/internal/serv/internal/migrate/testdata/gap/003_irreversible.sql diff --git a/migrate/testdata/noforward/001_create_no_forward.sql b/cmd/internal/serv/internal/migrate/testdata/noforward/001_create_no_forward.sql similarity index 100% rename from migrate/testdata/noforward/001_create_no_forward.sql rename to cmd/internal/serv/internal/migrate/testdata/noforward/001_create_no_forward.sql diff --git a/migrate/testdata/sample/001_create_t1.sql b/cmd/internal/serv/internal/migrate/testdata/sample/001_create_t1.sql similarity index 100% rename from migrate/testdata/sample/001_create_t1.sql rename to cmd/internal/serv/internal/migrate/testdata/sample/001_create_t1.sql diff --git a/migrate/testdata/sample/002_create_t2.sql b/cmd/internal/serv/internal/migrate/testdata/sample/002_create_t2.sql similarity index 100% rename from migrate/testdata/sample/002_create_t2.sql rename to cmd/internal/serv/internal/migrate/testdata/sample/002_create_t2.sql diff --git a/migrate/testdata/sample/003_irreversible.sql b/cmd/internal/serv/internal/migrate/testdata/sample/003_irreversible.sql similarity index 100% rename from migrate/testdata/sample/003_irreversible.sql rename to cmd/internal/serv/internal/migrate/testdata/sample/003_irreversible.sql diff --git a/migrate/testdata/sample/004_data_interpolation.sql b/cmd/internal/serv/internal/migrate/testdata/sample/004_data_interpolation.sql similarity index 100% rename from migrate/testdata/sample/004_data_interpolation.sql rename to cmd/internal/serv/internal/migrate/testdata/sample/004_data_interpolation.sql diff --git a/migrate/testdata/sample/005_template_inclusion.sql b/cmd/internal/serv/internal/migrate/testdata/sample/005_template_inclusion.sql similarity index 100% rename from migrate/testdata/sample/005_template_inclusion.sql rename to cmd/internal/serv/internal/migrate/testdata/sample/005_template_inclusion.sql diff --git a/migrate/testdata/sample/shared/v1_001.sql b/cmd/internal/serv/internal/migrate/testdata/sample/shared/v1_001.sql similarity index 100% rename from migrate/testdata/sample/shared/v1_001.sql rename to cmd/internal/serv/internal/migrate/testdata/sample/shared/v1_001.sql diff --git a/migrate/testdata/sample/should_be_ignored.sql b/cmd/internal/serv/internal/migrate/testdata/sample/should_be_ignored.sql similarity index 100% rename from migrate/testdata/sample/should_be_ignored.sql rename to cmd/internal/serv/internal/migrate/testdata/sample/should_be_ignored.sql diff --git a/rails/auth.go b/cmd/internal/serv/internal/rails/auth.go similarity index 100% rename from rails/auth.go rename to cmd/internal/serv/internal/rails/auth.go diff --git a/rails/auth_test.go b/cmd/internal/serv/internal/rails/auth_test.go similarity index 100% rename from rails/auth_test.go rename to cmd/internal/serv/internal/rails/auth_test.go diff --git a/rails/cookie.go b/cmd/internal/serv/internal/rails/cookie.go similarity index 100% rename from rails/cookie.go rename to cmd/internal/serv/internal/rails/cookie.go diff --git a/serv/introsp.go b/cmd/internal/serv/introsp.go similarity index 100% rename from serv/introsp.go rename to cmd/internal/serv/introsp.go diff --git a/serv/reload.go b/cmd/internal/serv/reload.go similarity index 97% rename from serv/reload.go rename to cmd/internal/serv/reload.go index ef1c8dd..850db72 100644 --- a/serv/reload.go +++ b/cmd/internal/serv/reload.go @@ -116,7 +116,7 @@ func Do(log func(string, ...interface{}), additional ...dir) error { continue } - logger.Info().Msgf("Reloading, file changed detected '%s'", event) + log("INF Reloading, file changed detected: %s", event) var trigger bool switch runtime.GOOS { @@ -172,7 +172,7 @@ func Do(log func(string, ...interface{}), additional ...dir) error { func ReExec() { err := syscall.Exec(binSelf, append([]string{binSelf}, os.Args[1:]...), os.Environ()) if err != nil { - errlog.Fatal().Err(err).Msg("cannot restart") + log.Fatalf("ERR cannot restart: %s", err) } } diff --git a/serv/rice-box.go b/cmd/internal/serv/rice-box.go similarity index 78% rename from serv/rice-box.go rename to cmd/internal/serv/rice-box.go index 7c31f3a..3113f09 100644 --- a/serv/rice-box.go +++ b/cmd/internal/serv/rice-box.go @@ -11,290 +11,36 @@ func init() { // define files file2 := &embedded.EmbeddedFile{ - Filename: "asset-manifest.json", - FileModTime: time.Unix(1582490894, 0), - - Content: string("{\n \"files\": {\n \"main.css\": \"/static/css/main.c6b5c55c.chunk.css\",\n \"main.js\": \"/static/js/main.968c4673.chunk.js\",\n \"main.js.map\": \"/static/js/main.968c4673.chunk.js.map\",\n \"runtime-main.js\": \"/static/js/runtime-main.4aea9da3.js\",\n \"runtime-main.js.map\": \"/static/js/runtime-main.4aea9da3.js.map\",\n \"static/js/2.2ead22c2.chunk.js\": \"/static/js/2.2ead22c2.chunk.js\",\n \"static/js/2.2ead22c2.chunk.js.map\": \"/static/js/2.2ead22c2.chunk.js.map\",\n \"index.html\": \"/index.html\",\n \"precache-manifest.d578bd2578bb3d4c1141f8579d17719e.js\": \"/precache-manifest.d578bd2578bb3d4c1141f8579d17719e.js\",\n \"service-worker.js\": \"/service-worker.js\",\n \"static/css/main.c6b5c55c.chunk.css.map\": \"/static/css/main.c6b5c55c.chunk.css.map\",\n \"static/media/GraphQLLanguageService.js.flow\": \"/static/media/GraphQLLanguageService.js.5ab204b9.flow\",\n \"static/media/autocompleteUtils.js.flow\": \"/static/media/autocompleteUtils.js.4ce7ba19.flow\",\n \"static/media/getAutocompleteSuggestions.js.flow\": \"/static/media/getAutocompleteSuggestions.js.7f98f032.flow\",\n \"static/media/getDefinition.js.flow\": \"/static/media/getDefinition.js.4dbec62f.flow\",\n \"static/media/getDiagnostics.js.flow\": \"/static/media/getDiagnostics.js.65b0979a.flow\",\n \"static/media/getHoverInformation.js.flow\": \"/static/media/getHoverInformation.js.d9411837.flow\",\n \"static/media/getOutline.js.flow\": \"/static/media/getOutline.js.c04e3998.flow\",\n \"static/media/index.js.flow\": \"/static/media/index.js.02c24280.flow\",\n \"static/media/logo.png\": \"/static/media/logo.57ee3b60.png\"\n },\n \"entrypoints\": [\n \"static/js/runtime-main.4aea9da3.js\",\n \"static/js/2.2ead22c2.chunk.js\",\n \"static/css/main.c6b5c55c.chunk.css\",\n \"static/js/main.968c4673.chunk.js\"\n ]\n}"), - } - file3 := &embedded.EmbeddedFile{ - Filename: "favicon.ico", - FileModTime: time.Unix(1582490855, 0), - - Content: string("\x00\x00\x01\x00\x03\x0000\x00\x00\x01\x00 \x00\xa8%\x00\x006\x00\x00\x00 \x00\x00\x01\x00 \x00\xa8\x10\x00\x00\xde%\x00\x00\x10\x10\x00\x00\x01\x00 \x00h\x04\x00\x00\x866\x00\x00(\x00\x00\x000\x00\x00\x00`\x00\x00\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x02\xaeRW\f\xaeRW\x18\xaeRW&\xaeRW3\xaeRW>\xaeRWG\xaeRWM\xaeRWP\xaeRWP\xaeRWM\xaeRWG\xaeRW>\xaeRW3\xaeRW&\xaeRW\x18\xaeRW\f\xaeRW\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\f\xaeRW*\xaeRWT\xaeRW\u007f\xaeRW\xa4\xaeRW\xc1\xaeRWծRW\xe2\xaeRW\xeb\xaeRW\xf1\xaeRW\xf4\xaeRW\xf6\xaeRW\xf7\xaeRW\xf7\xaeRW\xf6\xaeRW\xf4\xaeRW\xf1\xaeRW\xeb\xaeRW\xe2\xaeRWծRW\xc1\xaeRW\xa4\xaeRW\u007f\xaeRWT\xaeRW*\xaeRW\f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\f\xaeRW=\xaeRW\x81\xaeRW\xbe\xaeRW\xe4\xaeRW\xf7\xaeRW\xfd\xaeRW\xfe\xaeRW\xfd\xaeRW\xfc\xaeRW\xfc\xaeRW\xfb\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfb\xaeRW\xfc\xaeRW\xfc\xaeRW\xfd\xaeRW\xfe\xaeRW\xfd\xaeRW\xf7\xaeRW\xe4\xaeRW\xbe\xaeRW\x81\xaeRW<\xaeRW\f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x0e\xaeRW[\xaeRW\xb8\xaeRW\xed\xaeRW\xfd\xaeRW\xfd\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xfd\xaeRW\xed\xaeRW\xb8\xaeRW[\xaeRW\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW,\xaeRW\xaf\xaeRW\xf6\xaeRW\xfe\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xf6\xaeRW\xaf\xaeRW+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1e\xaeRWŮRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRWĮRW\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWi\xaeRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWi\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x80\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfb\xaeRW\xfc\xaeRW\xfd\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfd\xaeRW\xfc\xaeRW\xfb\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRW\xfd\xaeRW\xfe\xaeRW\xfc\xaeRW\xf7\xaeRW\xee\xaeRW\xe3\xaeRWخRW̮RW®RW\xbb\xaeRW\xb7\xaeRW\xb5\xaeRW\xb5\xaeRW\xb7\xaeRW\xbc\xaeRW®RW̮RWخRW\xe3\xaeRW\xee\xaeRW\xf7\xaeRW\xfc\xaeRW\xfe\xaeRW\xfd\xaeRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRW\xfe\xaeRW\xf7\xaeRW\xe2\xaeRW\xbf\xaeRW\x97\xaeRWq\xaeRWQ\xaeRW8\xaeRW&\xaeRW\x1a\xaeRW\x12\xaeRW\f\xaeRW\t\xaeRW\a\xaeRW\a\xaeRW\a\xaeRW\a\xaeRW\t\xaeRW\f\xaeRW\x12\xaeRW\x1a\xaeRW&\xaeRW8\xaeRWQ\xaeRWq\xaeRW\x97\xaeRW\xbf\xaeRW\xe2\xaeRW\xf7\xaeRW\xfe\xaeRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfd\xaeRW\xf9\xaeRW\u05eeRW\x99\xaeRWX\xaeRW'\xaeRW\f\xaeRW\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\xaeRV\x01\xaeRW\f\xaeRW'\xaeRWX\xaeRW\x99\xaeRW\u05eeRW\xf9\xaeRW\xfd\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x81\xaeRW\xfb\xaeRW®RWe\xaeRW\x1e\xaeRW\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x06\xaeRW\x12\xaeRW!\xaeRW1\xaeRW?\xaeRWL\xaeRWU\xaeRW[\xaeRW_\xaeRW_\xaeRW[\xaeRWU\xaeRWL\xaeRW?\xaeRW1\xaeRW!\xaeRW\x12\xaeRW\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x02\xaeRW\x1e\xaeRWf\xaeRW®RW\xfb\xaeRW\x81\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWa\xaeRWl\xaeRW\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRV\x01\xaeRW\x12\xaeRW5\xaeRWb\xaeRW\x8d\xaeRW\xb1\xaeRW̮RWޮRW\xea\xaeRW\xf1\xaeRW\xf6\xaeRW\xf8\xaeRW\xf9\xaeRW\xfa\xaeRW\xfa\xaeRW\xf9\xaeRW\xf8\xaeRW\xf6\xaeRW\xf1\xaeRW\xea\xaeRWޮRW̮RW\xb1\xaeRW\x8d\xaeRWb\xaeRW5\xaeRW\x12\xaeRW\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x12\xaeRWl\xaeRWa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\a\xaeRW\x02\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x11\xaeRWI\xaeRW\x8f\xaeRWɮRW\xeb\xaeRW\xfa\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfc\xaeRW\xfb\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfb\xaeRW\xfc\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfa\xaeRW\xeb\xaeRWɮRW\x8f\xaeRWI\xaeRW\x11\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x02\xaeRW\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x13\xaeRWh\xaeRWĮRW\xf2\xaeRW\xfe\xaeRW\xfd\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfd\xaeRW\xfe\xaeRW\xf2\xaeRWĮRWh\xaeRW\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW4\xaeRW\xbb\xaeRW\xf9\xaeRW\xfd\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfd\xaeRW\xf9\xaeRW\xba\xaeRW4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW#\xaeRW̮RW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW̮RW#\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWl\xaeRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWl\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x80\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfc\xaeRW\xfd\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfd\xaeRW\xfc\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRW\xfe\xaeRW\xfe\xaeRW\xfb\xaeRW\xf3\xaeRW\xe9\xaeRWܮRWϮRWîRW\xb9\xaeRW\xb1\xaeRW\xac\xaeRW\xa9\xaeRW\xa9\xaeRW\xac\xaeRW\xb1\xaeRW\xb9\xaeRWîRWϮRWܮRW\xe9\xaeRW\xf3\xaeRW\xfb\xaeRW\xfe\xaeRW\xfe\xaeRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfd\xaeRW\xfe\xaeRW\xf4\xaeRWۮRW\xb5\xaeRW\x8b\xaeRWe\xaeRWE\xaeRW/\xaeRW\x1f\xaeRW\x14\xaeRW\r\xaeRW\b\xaeRW\x05\xaeRW\x04\xaeRW\x03\xaeRW\x03\xaeRW\x04\xaeRW\x05\xaeRW\b\xaeRW\r\xaeRW\x14\xaeRW\x1f\xaeRW/\xaeRWE\xaeRWe\xaeRW\x8b\xaeRW\xb5\xaeRWۮRW\xf4\xaeRW\xfe\xaeRW\xfd\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfd\xaeRW\xf6\xaeRWϮRW\x8e\xaeRWL\xaeRW \xaeRW\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\b\xaeRW \xaeRWM\xaeRW\x8e\xaeRWЮRW\xf6\xaeRW\xfd\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x82\xaeRW\xf8\xaeRW\xb8\xaeRW[\xaeRW\x18\xaeQW\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeQV\x01\xaeRW\b\xaeRW\x16\xaeRW'\xaeRW8\xaeRWH\xaeRWV\xaeRWa\xaeRWh\xaeRWk\xaeRWl\xaeRWi\xaeRWc\xaeRWY\xaeRWL\xaeRW<\xaeRW+\xaeRW\x19\xaeRW\v\xaeRW\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeQV\x01\xaeRW\x18\xaeRW[\xaeRW\xb8\xaeRW\xf8\xaeRW\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\\\xaeRWa\xaeRW\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x02\xaeRW\x16\xaeRW<\xaeRWi\xaeRW\x94\xaeRW\xb8\xaeRWҮRW\xe3\xaeRW\xee\xaeRW\xf4\xaeRW\xf8\xaeRW\xfa\xaeRW\xfb\xaeRW\xfc\xaeRW\xfc\xaeRW\xfc\xaeRW\xfb\xaeRW\xf9\xaeRW\xf6\xaeRW\xf0\xaeRW\xe6\xaeRW֮RW\xbe\xaeRW\x9b\xaeRWp\xaeRWA\xaeRW\x19\xaeRW\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x0e\xaeRWa\xaeRW\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x05\xaeRW\x01\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x17\xaeRWS\xaeRW\x9a\xaeRWЮRW\xef\xaeRW\xfb\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfb\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfb\xaeRW\xfc\xaeRW\xfe\xaeRW\xfe\xaeRW\xfc\xaeRW\xf1\xaeRWԮRW\x9d\xaeRWV\xaeRW\x18\xaeQV\x01\x00\x00\x00\x00\xaeRW\x01\xaeRW\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\xaeRW\x18\xaeRWr\xaeRW̮RW\xf6\xaeRW\xfe\xaeRW\xfd\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfc\xaeRW\xfe\xaeRW\xf6\xaeRWήRWv\xaeRW\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW:\xaeRW®RW\xfa\xaeRW\xfd\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfd\xaeRW\xfb\xaeRWŮRW=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW&\xaeRWѮRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRWӮRW(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWo\xaeRW\xfd\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfd\xaeRWo\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x80\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\u007f\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x80\xaeRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfe\xaeRW\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWi\xaeRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWg\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWŮRW\xfe\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xc1\xaeRW\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW,\xaeRW\xb0\xaeRW\xf6\xaeRW\xfe\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xf5\xaeRW\xaa\xaeRW(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x0e\xaeRW[\xaeRW\xb9\xaeRW\xed\xaeRW\xfd\xaeRW\xfd\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRW\xfe\xaeRW\xfd\xaeRW\xec\xaeRW\xb5\xaeRWW\xaeRW\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\f\xaeRW=\xaeRW\x82\xaeRW\xbe\xaeRW\xe5\xaeRW\xf7\xaeRW\xfd\xaeRW\xfe\xaeRW\xfd\xaeRW\xfc\xaeRW\xfb\xaeRW\xfb\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfb\xaeRW\xfc\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xf5\xaeRW\xe1\xaeRW\xba\xaeRW~\xaeRW;\xaeRW\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\f\xaeRW+\xaeRWT\xaeRW\u007f\xaeRW\xa4\xaeRW\xc1\xaeRW֮RW\xe3\xaeRW\xec\xaeRW\xf1\xaeRW\xf5\xaeRW\xf6\xaeRW\xf7\xaeRW\xf7\xaeRW\xf6\xaeRW\xf4\xaeRW\xf1\xaeRW\xeb\xaeRW\xe1\xaeRWӮRW\xbd\xaeRW\x9f\xaeRWx\xaeRWM\xaeRW&\xaeRW\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x02\xaeRW\f\xaeRW\x19\xaeRW&\xaeRW3\xaeRW>\xaeRWH\xaeRWN\xaeRWP\xaeRWP\xaeRWM\xaeRWF\xaeRW>\xaeRW2\xaeRW$\xaeRW\x17\xaeRW\n\xaeRW\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00\xff\xfe\x00\x00\u007f\xff\x00\x00\xff\xc0\x00\x00\x03\xff\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfc\x00\x00\x00\x00?\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf0\x00\x00\x00\x00\x0f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x03\xff\xff\xc0\x1f\x00\x00\xf8?\xff\xff\xfc\x1f\x00\x00\xf1\xff\xff\xff\xff\x8f\x00\x00\xff\xfc\x00\x00?\xff\x00\x00\xff\xc0\x00\x00\x03\xff\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfc\x00\x00\x00\x00?\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf0\x00\x00\x00\x00\x0f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x03\xff\xff\xc0\x1f\x00\x00\xf8?\xff\xff\xfc\x1f\x00\x00\xf1\xff\xff\xff\xff\x8f\x00\x00\xff\xfc\x00\x00?\xff\x00\x00\xff\xc0\x00\x00\x03\xff\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfc\x00\x00\x00\x00?\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf0\x00\x00\x00\x00\x0f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf0\x00\x00\x00\x00\x0f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xf8\x00\x00\x00\x00\x1f\x00\x00\xfc\x00\x00\x00\x00?\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xff\xc0\x00\x00\a\xff\x00\x00\xff\xfe\x00\x00\u007f\xff\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x04\xaeRW\n\xaeRW\x0e\xaeRW\x10\xaeRW\x10\xaeRW\x0e\xaeRW\n\xaeRW\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\r\xaeRW,\xaeRWS\xaeRWw\xaeRW\x95\xaeRW\xaa\xaeRW\xb9\xaeRW\xc1\xaeRWŮRWŮRW\xc1\xaeRW\xb9\xaeRW\xaa\xaeRW\x95\xaeRWw\xaeRWS\xaeRW,\xaeRW\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x05\xaeRW3\xaeRW\u007f\xaeRW\xc0\xaeRW\xe6\xaeRW\xf7\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfd\xaeRW\xfd\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xf7\xaeRW\xe6\xaeRW\xc0\xaeRW\u007f\xaeRW3\xaeRW\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\xaeRW\x1b\xaeRW\x92\xaeRW\xe7\xaeRW\xfd\xaeRW\xfd\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfd\xaeRW\xfd\xaeRW\xe7\xaeRW\x91\xaeRW\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\b\xaeRW\xa2\xaeRW\xfe\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xa2\xaeRW\b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1d\xaeRWܮRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWܮRW\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfc\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfc\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xfc\xaeRW\xfc\xaeRW\xfe\xaeRW\xfb\xaeRW\xef\xaeRWڮRWîRW\xad\xaeRW\x9a\xaeRW\x8c\xaeRW\x83\xaeRW\x80\xaeRW\x80\xaeRW\x83\xaeRW\x8c\xaeRW\x9a\xaeRW\xad\xaeRWîRWڮRW\xef\xaeRW\xfb\xaeRW\xfe\xaeRW\xfc\xaeRW\xfc\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRW߮RW\xfd\xaeRW\xe0\xaeRW\xa8\xaeRWk\xaeRW;\xaeRW\x1c\xaeRW\t\xaeQV\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\xaeQW\x01\xaeRW\t\xaeRW\x1c\xaeRW;\xaeRWk\xaeRW\xa8\xaeRW\xe0\xaeRW\xfd\xaeRW߮RW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRW\xbc\xaeRW}\xaeRW'\xaeRW\x03\x00\x00\x00\x00\xaeRW\a\xaeRW\x1f\xaeRW<\xaeRWW\xaeRWm\xaeRW}\xaeRW\x88\xaeRW\x8d\xaeRW\x8d\xaeRW\x88\xaeRW}\xaeRWm\xaeRWW\xaeRW<\xaeRW\x1f\xaeRW\a\x00\x00\x00\x00\xaeRW\x03\xaeRW'\xaeRW}\xaeRW\xbc\xaeRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\n\xaeRW\x1d\xaeQW\x01\xaeRW\x0e\xaeRWC\xaeRW\x86\xaeRW\xbb\xaeRWݮRW\xf0\xaeRW\xf8\xaeRW\xfc\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfc\xaeRW\xf8\xaeRW\xf0\xaeRWݮRW\xbb\xaeRW\x86\xaeRWC\xaeRW\x0e\xaeRW\x01\xaeRW\x1d\xaeRW\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\b\xaeRWX\xaeRW\xbf\xaeRW\xf1\xaeRW\xfe\xaeRW\xfe\xaeRW\xfc\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfc\xaeRW\xfe\xaeRW\xfd\xaeRW\xf1\xaeRW\xbe\xaeRWX\xaeRW\b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x02\xaeRWz\xaeRW\xf3\xaeRW\xfe\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xf3\xaeRWz\xaeRW\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x19\xaeRW\u05eeRW\xfd\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfd\xaeRW\u05eeRW\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfc\xaeRW\xfd\xaeRW\xfd\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfd\xaeRW\xfd\xaeRW\xfc\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xfc\xaeRW\xfa\xaeRW\xfc\xaeRW\xfe\xaeRW\xfd\xaeRW\xf6\xaeRW\xeb\xaeRWޮRWҮRWǮRW\xc0\xaeRW\xbd\xaeRW\xbd\xaeRW\xc0\xaeRWǮRWҮRWޮRW\xeb\xaeRW\xf6\xaeRW\xfd\xaeRW\xfe\xaeRW\xfc\xaeRW\xfa\xaeRW\xfc\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xff\xaeRW\xf8\xaeRWڮRW\xaa\xaeRWx\xaeRWO\xaeRW2\xaeRW\x1f\xaeRW\x12\xaeRW\v\xaeRW\a\xaeRW\x05\xaeRW\x05\xaeRW\a\xaeRW\v\xaeRW\x12\xaeRW\x1f\xaeRW2\xaeRWO\xaeRWx\xaeRW\xaa\xaeRWڮRW\xf8\xaeRW\xff\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW \xaeRW֮RW\xb9\xaeRW^\xaeRW\x1e\xaeRW\x03\x00\x00\x00\x00\xaeRW\x01\xaeRW\r\xaeRW\x1f\xaeRW0\xaeRW>\xaeRWH\xaeRWL\xaeRWM\xaeRWI\xaeRW@\xaeRW2\xaeRW!\xaeRW\x0f\xaeRW\x02\x00\x00\x00\x00\xaeRW\x03\xaeRW\x1e\xaeRW^\xaeRW\xb9\xaeRW֮RW \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x12\xaeRWH\xaeRW\r\x00\x00\x00\x00\xaeRW\x15\xaeRWF\xaeRW{\xaeRW\xa9\xaeRWɮRWޮRW\xea\xaeRW\xf1\xaeRW\xf5\xaeRW\xf6\xaeRW\xf6\xaeRW\xf5\xaeRW\xf2\xaeRW\xec\xaeRW\xe0\xaeRWͮRW\xad\xaeRW\x80\xaeRWI\xaeRW\x16\x00\x00\x00\x00\xaeRW\r\xaeRWH\xaeRW\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW&\xaeRW\x83\xaeRWϮRW\xf2\xaeRW\xfd\xaeRW\xfe\xaeRW\xfd\xaeRW\xfc\xaeRW\xfb\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfc\xaeRW\xfd\xaeRW\xfe\xaeRW\xfd\xaeRW\xf3\xaeRWЮRW\x86\xaeRW(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWL\xaeRW֮RW\xfd\xaeRW\xfd\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfd\xaeRW\xfd\xaeRWخRWN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x13\xaeRWɮRW\xff\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xff\xaeRWʮRW\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1f\xaeRWݮRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWݮRW\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1d\xaeRWܮRW\xfc\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRWܮRW\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\b\xaeRW\xa2\xaeRW\xfe\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfc\xaeRW\xfe\xaeRW\xa0\xaeRW\b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1b\xaeRW\x92\xaeRW\xe7\xaeRW\xfd\xaeRW\xfd\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xfd\xaeRW\xe6\xaeRW\x8e\xaeRW\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x05\xaeRW3\xaeRW\x80\xaeRW\xc0\xaeRW\xe6\xaeRW\xf7\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xfd\xaeRW\xfd\xaeRW\xfd\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfd\xaeRW\xf6\xaeRW\xe4\xaeRW\xbe\xaeRW~\xaeRW1\xaeRW\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\r\xaeRW,\xaeRWS\xaeRWx\xaeRW\x95\xaeRW\xab\xaeRW\xb9\xaeRW®RWŮRWŮRW\xc1\xaeRW\xb8\xaeRW\xa9\xaeRW\x93\xaeRWt\xaeRWN\xaeRW)\xaeRW\f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x04\xaeRW\n\xaeRW\x0e\xaeRW\x10\xaeRW\x10\xaeRW\x0e\xaeRW\t\xaeRW\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xe0\a\xff\xfe\x00\x00\u007f\xf0\x00\x00\x0f\xe0\x00\x00\a\xe0\x00\x00\a\xe0\x00\x00\a\xe0\x00\x00\a\xe0\x00\x00\a\xe1\xff\xff\x87\xef\xfc?\xf7\xfe\x00\x00\u007f\xf8\x00\x00\x1f\xf0\x00\x00\x0f\xe0\x00\x00\a\xe0\x00\x00\a\xe0\x00\x00\a\xe0\x00\x00\a\xe0\xff\xff\a\xe7\xff\xff\xe7\xff\x80\x00\xff\xf8\x00\x00\x1f\xf0\x00\x00\x0f\xe0\x00\x00\a\xe0\x00\x00\a\xe0\x00\x00\a\xe0\x00\x00\a\xe0\x00\x00\a\xf0\x00\x00\x0f\xfc\x00\x00\u007f\xff\xe0\a\xff\xff\xff\xff\xff(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x10\xaeRW3\xaeRWW\xaeRWo\xaeRW{\xaeRW{\xaeRWo\xaeRWW\xaeRW3\xaeRW\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x0f\xaeRWl\xaeRW\xbf\xaeRW\xe5\xaeRW\xf4\xaeRW\xf9\xaeRW\xfa\xaeRW\xfa\xaeRW\xf9\xaeRW\xf4\xaeRW\xe5\xaeRW\xbf\xaeRWl\xaeRW\x0f\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWf\xaeRW\xfa\xaeRW\xfe\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xfa\xaeRWf\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW~\xaeRW\xff\xaeRW\xfe\xaeRW\xfe\xaeRW\xfb\xaeRW\xf7\xaeRW\xf5\xaeRW\xf5\xaeRW\xf7\xaeRW\xfb\xaeRW\xfe\xaeRW\xfe\xaeRW\xff\xaeRW~\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW~\xaeRW\xeb\xaeRW\xb4\xaeRW\x83\xaeRWe\xaeRWV\xaeRWQ\xaeRWQ\xaeRWV\xaeRWe\xaeRW\x83\xaeRW\xb4\xaeRW\xeb\xaeRW~\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW:\xaeRWF\xaeRWF\xaeRWp\xaeRW\x95\xaeRW\xaa\xaeRW\xb4\xaeRW\xb4\xaeRW\xaa\xaeRW\x95\xaeRWp\xaeRWF\xaeRWF\xaeRW:\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW)\xaeRW\xb0\xaeRW\xee\xaeRW\xfc\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfe\xaeRW\xfc\xaeRW\xee\xaeRW\xb0\xaeRW)\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWx\xaeRW\xff\xaeRW\xfb\xaeRW\xfb\xaeRW\xfc\xaeRW\xfc\xaeRW\xfd\xaeRW\xfd\xaeRW\xfc\xaeRW\xfc\xaeRW\xfb\xaeRW\xfb\xaeRW\xff\xaeRWx\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW~\xaeRW\xff\xaeRW\xfb\xaeRW\xef\xaeRW߮RWҮRWˮRWˮRWҮRW߮RW\xef\xaeRW\xfb\xaeRW\xff\xaeRW~\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWt\xaeRW\xb8\xaeRWl\xaeRWG\xaeRW?\xaeRWB\xaeRWE\xaeRWF\xaeRWC\xaeRW@\xaeRWH\xaeRWl\xaeRW\xb8\xaeRWt\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x1c\xaeRWC\xaeRW\x81\xaeRW\xb7\xaeRW֮RW\xe4\xaeRW\xea\xaeRW\xea\xaeRW\xe5\xaeRW\u05eeRW\xb9\xaeRW\x83\xaeRWD\xaeRW\x1c\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWK\xaeRW\xe4\xaeRW\xfe\xaeRW\xfe\xaeRW\xfc\xaeRW\xfb\xaeRW\xfb\xaeRW\xfb\xaeRW\xfb\xaeRW\xfc\xaeRW\xfe\xaeRW\xfe\xaeRW\xe5\xaeRWL\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW~\xaeRW\xff\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xff\xaeRW~\x00\x00\x00\x00\x00\x00\x00\x00\xaeRWf\xaeRW\xfa\xaeRW\xfe\xaeRW\xfb\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfa\xaeRW\xfb\xaeRW\xfe\xaeRW\xf9\xaeRWf\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x0f\xaeRWl\xaeRW\xbf\xaeRW\xe5\xaeRW\xf4\xaeRW\xf9\xaeRW\xfa\xaeRW\xfa\xaeRW\xf9\xaeRW\xf3\xaeRW\xe4\xaeRW\xbe\xaeRWk\xaeRW\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaeRW\x10\xaeRW4\xaeRWW\xaeRWp\xaeRW{\xaeRW{\xaeRWo\xaeRWU\xaeRW2\xaeRW\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\xe0\a\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xc7\xe3\x00\x00\xf8\x1f\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xdf\xfb\x00\x00\xe0\a\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xe0\a\x00\x00\xff\xff\x00\x00"), - } - file4 := &embedded.EmbeddedFile{ - Filename: "index.html", - FileModTime: time.Unix(1582490894, 0), - - Content: string("
f+p-3&&(a.scrollLeft=t.right+(d?0:10)-f),a}function Or(e,t){null!=t&&(Ir(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function Fr(e){Ir(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function Nr(e,t,n){null==t&&null==n||Ir(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function Ir(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,jr(e,Jn(e,t.from),Jn(e,t.to),t.margin))}function jr(e,t,n,r){var i=_r(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});Nr(e,i.scrollLeft,i.scrollTop)}function Mr(e,t){Math.abs(e.doc.scrollTop-t)<2||(n||ui(e,{top:t}),Pr(e,t,!0),n&&ui(e),ri(e,100))}function Pr(e,t,n){t=Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t),(e.display.scroller.scrollTop!=t||n)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Lr(e,t,n,r){t=Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,pi(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Rr(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+wn(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+kn(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}var Br=function(e,t,n){this.cm=n;var r=this.vert=_(\"div\",[_(\"div\",null,null,\"min-width: 1px\")],\"CodeMirror-vscrollbar\"),i=this.horiz=_(\"div\",[_(\"div\",null,null,\"height: 100%; min-height: 1px\")],\"CodeMirror-hscrollbar\");r.tabIndex=i.tabIndex=-1,e(r),e(i),fe(r,\"scroll\",(function(){r.clientHeight&&t(r.scrollTop,\"vertical\")})),fe(i,\"scroll\",(function(){i.clientWidth&&t(i.scrollLeft,\"horizontal\")})),this.checkedZeroWidth=!1,a&&s<8&&(this.horiz.style.minHeight=this.vert.style.minWidth=\"18px\")};Br.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,n=e.scrollHeight>e.clientHeight+1,r=e.nativeBarWidth;if(n){this.vert.style.display=\"block\",this.vert.style.bottom=t?r+\"px\":\"0\";var i=e.viewHeight-(t?r:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+\"px\"}else this.vert.style.display=\"\",this.vert.firstChild.style.height=\"0\";if(t){this.horiz.style.display=\"block\",this.horiz.style.right=n?r+\"px\":\"0\",this.horiz.style.left=e.barLeft+\"px\";var o=e.viewWidth-e.barLeft-(n?r:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+\"px\"}else this.horiz.style.display=\"\",this.horiz.firstChild.style.width=\"0\";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==r&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:n?r:0,bottom:t?r:0}},Br.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,\"horiz\")},Br.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,\"vert\")},Br.prototype.zeroWidthHack=function(){var e=y&&!d?\"12px\":\"18px\";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents=\"none\",this.disableHoriz=new B,this.disableVert=new B},Br.prototype.enableZeroWidthBar=function(e,t,n){e.style.pointerEvents=\"auto\",t.set(1e3,(function r(){var i=e.getBoundingClientRect();(\"vert\"==n?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1))!=e?e.style.pointerEvents=\"none\":t.set(1e3,r)}))},Br.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var Ur=function(){};function zr(e,t){t||(t=Rr(e));var n=e.display.barWidth,r=e.display.barHeight;Vr(e,t);for(var i=0;i<4&&n!=e.display.barWidth||r!=e.display.barHeight;i++)n!=e.display.barWidth&&e.options.lineWrapping&&kr(e),Vr(e,Rr(e)),n=e.display.barWidth,r=e.display.barHeight}function Vr(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+\"px\",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+\"px\",n.heightForcer.style.borderBottom=r.bottom+\"px solid transparent\",r.right&&r.bottom?(n.scrollbarFiller.style.display=\"block\",n.scrollbarFiller.style.height=r.bottom+\"px\",n.scrollbarFiller.style.width=r.right+\"px\"):n.scrollbarFiller.style.display=\"\",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display=\"block\",n.gutterFiller.style.height=r.bottom+\"px\",n.gutterFiller.style.width=t.gutterWidth+\"px\"):n.gutterFiller.style.display=\"\"}Ur.prototype.update=function(){return{bottom:0,right:0}},Ur.prototype.setScrollLeft=function(){},Ur.prototype.setScrollTop=function(){},Ur.prototype.clear=function(){};var qr={native:Br,null:Ur};function Hr(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&k(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new qr[e.options.scrollbarStyle]((function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),fe(t,\"mousedown\",(function(){e.state.focused&&setTimeout((function(){return e.display.input.focus()}),0)})),t.setAttribute(\"cm-not-content\",\"true\")}),(function(t,n){\"horizontal\"==n?Lr(e,t):Mr(e,t)}),e),e.display.scrollbars.addClass&&I(e.display.wrapper,e.display.scrollbars.addClass)}var Wr=0;function Gr(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Wr},t=e.curOp,an?an.ops.push(t):t.ownsGroup=an={ops:[t],delayedCallbacks:[]}}function Kr(e){var t=e.curOp;t&&function(e,t){var n=e.ownsGroup;if(n)try{!function(e){var t=e.delayedCallbacks,n=0;do{for(;n =Zt)return function(e,t,n,r,o){for(var a=0,s=new Array(i),u=0;0!==n;u++,n>>>=1)s[u]=1&n?t[a++]:void 0;return s[r]=o,new Lt(e,a+1,s)}(e,g,d,p,y);if(h&&!y&&2===g.length&&Jt(g[1^m]))return g[1^m];if(h&&y&&1===g.length&&Jt(y))return y;var b=e&&e===this.ownerID,E=h?y?d:d^f:d|f,x=h?y?Xt(g,m,y,b):function(e,t,n){var r=e.length-1;if(n&&t===r)return e.pop(),e;for(var i=new Array(r),o=0,a=0;a h?new an([],i):g;if(g&&m>h&&c a&&(f=f.removeBefore(i,p,c-d)),f&&ms)return{value:void 0,done:!0};var e=i.next();return r||t===P||e.done?e:V(t,u-1,t===M?void 0:e.value[1],e)}))},c}function Le(e,t,n,r){var i=Ke(e);return i.__iterateUncached=function(i,o){var a=this;if(o)return this.cacheResult().__iterate(i,o);var s=!0,u=0;return e.__iterate((function(e,o,c){if(!s||!(s=t.call(n,e,o,c)))return u++,i(e,r?o:u-1,a)})),u},i.__iteratorUncached=function(i,o){var a=this;if(o)return this.cacheResult().__iterator(i,o);var s=e.__iterator(L,o),u=!0,c=0;return new z((function(){var e,o,l;do{if((e=s.next()).done)return r||i===P?e:V(i,c++,i===M?void 0:e.value[1],e);var p=e.value;o=p[0],l=p[1],u&&(u=t.call(n,l,o,a))}while(u);return i===L?e:V(i,o,l,e)}))},i}function Re(e,t){var n=E(e),r=[e].concat(t).map((function(e){return y(e)?n&&(e=S(e)):e=n?oe(e):ae(Array.isArray(e)?e:[e]),e})).filter((function(e){return 0!==e.size}));if(0===r.length)return e;if(1===r.length){var i=r[0];if(i===e||n&&E(i)||D(e)&&D(i))return i}var o=new ee(r);return n?o=o.toKeyedSeq():D(e)||(o=o.toSetSeq()),(o=o.flatten(!0)).size=r.reduce((function(e,t){if(void 0!==e){var n=t.size;if(void 0!==n)return e+n}}),0),o}function Be(e,t,n){var r=Ke(e);return r.__iterateUncached=function(i,o){if(o)return this.cacheResult().__iterate(i,o);var a=0,s=!1;return function e(u,c){u.__iterate((function(o,u){return(!t||cr;b-=r){var E=h>>>b&o;y=y.array[E]=dn(y.array[E],i)}y.array[h>>>r&o]=g}if(l=m)c-=m,l-=m,p=r,f=null,v=v&&v.removeBefore(i,0,c);else if(c>a||m