diff --git a/.clang-format b/.clang-format index f8238280d..a148e5429 100644 --- a/.clang-format +++ b/.clang-format @@ -6,7 +6,7 @@ AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlinesLeft: true -AlignOperands: true +AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false @@ -20,7 +20,7 @@ AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true -BraceWrapping: +BraceWrapping: AfterClass: false AfterControlStatement: false AfterEnum: false @@ -45,7 +45,6 @@ ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: true -PointerAlignment: Left DisableFormat: false ExperimentalAutoDetectBinPacking: false ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] diff --git a/bindings.go b/bindings.go index dffa2def8..55aad7c1f 100644 --- a/bindings.go +++ b/bindings.go @@ -542,3 +542,7 @@ func WithPrometheusMetrics() interface{} { func WithOpenTelemetry() interface{} { return bindings.OptionOpenTelemetry{EnableTracing: true} } + +func WithStrictJoinHandlers() interface{} { + return bindings.OptionStrictJoinHandlers{EnableStrictJoinHandlers: true} +} diff --git a/bindings/consts.go b/bindings/consts.go index 504f0a3e6..77d0c0b0b 100644 --- a/bindings/consts.go +++ b/bindings/consts.go @@ -24,12 +24,14 @@ const ( INFO = 3 TRACE = 4 - AggSum = 0 - AggAvg = 1 - AggFacet = 2 - AggMin = 3 - AggMax = 4 - AggDistinct = 5 + AggSum = 0 + AggAvg = 1 + AggFacet = 2 + AggMin = 3 + AggMax = 4 + AggDistinct = 5 + AggCount = 6 + AggCountCached = 7 CollateNone = 0 CollateASCII = 1 @@ -83,6 +85,9 @@ const ( QueryUpdateFieldV2 = 25 QueryBetweenFieldsCondition = 26 QueryAlwaysFalseCondition = 27 + QueryAlwaysTrueCondition = 28 + QuerySubQueryCondition = 29 + QueryFieldSubQueryCondition = 30 LeftJoin = 0 InnerJoin = 1 diff --git a/bindings/cproto/netbuf.go b/bindings/cproto/netbuf.go index 3ddb6e691..220432e0f 100644 --- a/bindings/cproto/netbuf.go +++ b/bindings/cproto/netbuf.go @@ -2,7 +2,6 @@ package cproto import ( "context" - "fmt" "sync" "time" @@ -103,7 +102,9 @@ func (buf *NetBuffer) close() { buf.reqID = -1 buf.uid = -1 if err != nil { - fmt.Printf("rx: query close error: %v\n", err) + if logger := buf.conn.owner.GetLogger(); logger != nil { + logger.Printf(bindings.ERROR, "rq: query close error: %v\n", err) + } } closeBuf.Free() } diff --git a/bindings/interface.go b/bindings/interface.go index 1f9e28d99..90ca77b1f 100644 --- a/bindings/interface.go +++ b/bindings/interface.go @@ -320,6 +320,12 @@ type OptionOpenTelemetry struct { EnableTracing bool } +// OptionStrictJoinHandlers - enables join handlers check. +// If enabled, queries without required join handlers or Joinable interface will return error after execution. +type OptionStrictJoinHandlers struct { + EnableStrictJoinHandlers bool +} + type Status struct { Err error CProto StatusCProto diff --git a/changelog.md b/changelog.md index 9d488b090..e447341c2 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,43 @@ +# Version 3.21.0 (XX.12.2023) +## Core +- [fea] Added [subqueries](#subqueries-nested-queries) support (`explain` for subqueries will be implement in the next releases) +- [fea] Added backtraces support for Windows platform +- [fea] Added query crash tracker support for Windows platform +- [fix] Added explicit error for aggregations in joined queries +- [fix] Fixed UPDATE-queries for array-indexes with multiple JSON-paths +- [fix] Fixed UPSERT/UPDATE for sparse arrays with null-values +- [fix] Optimized tagsmatcher's updates in UPDATE-queries + +## Replication +- [fea] Added some temporary replication fixes for v4-compatibility (one of the next v4 releases will contain v3-v4 compatibility mode for migration) + +## Reindexer server +- [fea] Added HTTP DSL for subqueries + +## Go connector +- [fea] Added Go API and DSL-convertor for subqueries +- [fea] Changed CJSON-to-object convetrion logic for slices: now the single JSON values and fields with multiple JSON-paths will be concatenated together in the target field +- [fea] Added `WithStrictJoinHandlers`. This option allows to validate JoinHandlers usage in runtime +- [fix] Fixed panic handling in the CJSON deserialization +- [fix] Fixed logging in `cproto`-binding. Error messages will no longer be redirected to stdout instead of user's logger + +## Face +- [fea] Saved the scroll position on the sorting +- [fea] Changed the Server ID range +- [fea] Improved the notification about the supported browsers +- [fea] Added the default values to the config form when the default config is using +- [fix] Fixed the wrong redirect to a fake database +- [fix] Fixed the column order changing on the data sorting +- [fix] Fixed the horizontal scroll on the data sorting +- [fix] Fixed the wrong data filtering in the Statistics tables +- [fix] Fixed the modal window with the notification about the JSON-tags clearing +- [fix] Fixed the "+/-" buttons for the inputs +- [fix] Fixed the console issue appeared on the array data sorting +- [fix] Fixed the layout of the Performance page +- [fix] Fixed the pagination buttons +- [fix] Fixed the misprint in Config + + # Version 3.20.0 (30.10.2023) ## Core - [fea] Added crash query report for Update/Delete queries diff --git a/cjson/creflect.go b/cjson/creflect.go index 78c2e9161..1f9943502 100644 --- a/cjson/creflect.go +++ b/cjson/creflect.go @@ -107,42 +107,42 @@ const hexChars = "0123456789abcdef" func createUuid(v [2]uint64) string { buf := make([]byte, 36) - buf[0] = hexChars[(v[0] >> 60) & 0xF]; - buf[1] = hexChars[(v[0] >> 56) & 0xF]; - buf[2] = hexChars[(v[0] >> 52) & 0xF]; - buf[3] = hexChars[(v[0] >> 48) & 0xF]; - buf[4] = hexChars[(v[0] >> 44) & 0xF]; - buf[5] = hexChars[(v[0] >> 40) & 0xF]; - buf[6] = hexChars[(v[0] >> 36) & 0xF]; - buf[7] = hexChars[(v[0] >> 32) & 0xF]; - buf[8] = '-'; - buf[9] = hexChars[(v[0] >> 28) & 0xF]; - buf[10] = hexChars[(v[0] >> 24) & 0xF]; - buf[11] = hexChars[(v[0] >> 20) & 0xF]; - buf[12] = hexChars[(v[0] >> 16) & 0xF]; - buf[13] = '-'; - buf[14] = hexChars[(v[0] >> 12) & 0xF]; - buf[15] = hexChars[(v[0] >> 8) & 0xF]; - buf[16] = hexChars[(v[0] >> 4) & 0xF]; - buf[17] = hexChars[v[0] & 0xF]; - buf[18] = '-'; - buf[19] = hexChars[(v[1] >> 60) & 0xF]; - buf[20] = hexChars[(v[1] >> 56) & 0xF]; - buf[21] = hexChars[(v[1] >> 52) & 0xF]; - buf[22] = hexChars[(v[1] >> 48) & 0xF]; - buf[23] = '-'; - buf[24] = hexChars[(v[1] >> 44) & 0xF]; - buf[25] = hexChars[(v[1] >> 40) & 0xF]; - buf[26] = hexChars[(v[1] >> 36) & 0xF]; - buf[27] = hexChars[(v[1] >> 32) & 0xF]; - buf[28] = hexChars[(v[1] >> 28) & 0xF]; - buf[29] = hexChars[(v[1] >> 24) & 0xF]; - buf[30] = hexChars[(v[1] >> 20) & 0xF]; - buf[31] = hexChars[(v[1] >> 16) & 0xF]; - buf[32] = hexChars[(v[1] >> 12) & 0xF]; - buf[33] = hexChars[(v[1] >> 8) & 0xF]; - buf[34] = hexChars[(v[1] >> 4) & 0xF]; - buf[35] = hexChars[v[1] & 0xF]; + buf[0] = hexChars[(v[0]>>60)&0xF] + buf[1] = hexChars[(v[0]>>56)&0xF] + buf[2] = hexChars[(v[0]>>52)&0xF] + buf[3] = hexChars[(v[0]>>48)&0xF] + buf[4] = hexChars[(v[0]>>44)&0xF] + buf[5] = hexChars[(v[0]>>40)&0xF] + buf[6] = hexChars[(v[0]>>36)&0xF] + buf[7] = hexChars[(v[0]>>32)&0xF] + buf[8] = '-' + buf[9] = hexChars[(v[0]>>28)&0xF] + buf[10] = hexChars[(v[0]>>24)&0xF] + buf[11] = hexChars[(v[0]>>20)&0xF] + buf[12] = hexChars[(v[0]>>16)&0xF] + buf[13] = '-' + buf[14] = hexChars[(v[0]>>12)&0xF] + buf[15] = hexChars[(v[0]>>8)&0xF] + buf[16] = hexChars[(v[0]>>4)&0xF] + buf[17] = hexChars[v[0]&0xF] + buf[18] = '-' + buf[19] = hexChars[(v[1]>>60)&0xF] + buf[20] = hexChars[(v[1]>>56)&0xF] + buf[21] = hexChars[(v[1]>>52)&0xF] + buf[22] = hexChars[(v[1]>>48)&0xF] + buf[23] = '-' + buf[24] = hexChars[(v[1]>>44)&0xF] + buf[25] = hexChars[(v[1]>>40)&0xF] + buf[26] = hexChars[(v[1]>>36)&0xF] + buf[27] = hexChars[(v[1]>>32)&0xF] + buf[28] = hexChars[(v[1]>>28)&0xF] + buf[29] = hexChars[(v[1]>>24)&0xF] + buf[30] = hexChars[(v[1]>>20)&0xF] + buf[31] = hexChars[(v[1]>>16)&0xF] + buf[32] = hexChars[(v[1]>>12)&0xF] + buf[33] = hexChars[(v[1]>>8)&0xF] + buf[34] = hexChars[(v[1]>>4)&0xF] + buf[35] = hexChars[v[1]&0xF] return string(buf) } @@ -201,6 +201,15 @@ func (pl *payloadIface) getArrayLen(field int) int { func (pl *payloadIface) getValue(field int, idx int, v reflect.Value) { k := v.Type().Kind() + if k == reflect.Slice { + el := reflect.New(v.Type().Elem()).Elem() + extSlice := reflect.Append(v, el) + v.Set(extSlice) + v = v.Index(v.Len() - 1) + k = v.Type().Kind() + } else if k == reflect.Array { + panic(fmt.Errorf("can not put single indexed value into the fixed size array")) + } switch pl.t.Fields[field].Type { case valueBool: v.SetBool(pl.getBool(field, idx)) @@ -229,7 +238,7 @@ func (pl *payloadIface) getValue(field int, idx int, v reflect.Value) { case valueUuid: v.SetString(pl.getUuid(field, idx)) default: - panic(fmt.Errorf("Unknown key value type %d", pl.t.Fields[field].Type)) + panic(fmt.Errorf("unknown key value type '%d'", pl.t.Fields[field].Type)) } } @@ -241,218 +250,362 @@ func (pl *payloadIface) getArray(field int, startIdx int, cnt int, v reflect.Val ptr := pl.ptr(field, startIdx, pl.t.Fields[field].Type) l := pl.getArrayLen(field) - startIdx + i := 0 switch pl.t.Fields[field].Type { case valueInt: - pi := (*[1 << 27]Cint)(ptr)[:l:l] - pu := (*[1 << 27]Cunsigned)(ptr)[:l:l] + pi := (*[1 << 27]Cint)(ptr)[:cnt:cnt] + pu := (*[1 << 27]Cunsigned)(ptr)[:cnt:cnt] switch a := v.Addr().Interface().(type) { case *[]int: - *a = make([]int, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = int(pi[i]) + if len(*a) == 0 { + *a = make([]int, cnt) + } else { + i = len(*a) + var tmp []int + tmp, *a = *a, make([]int, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = int(pi[j]) } case *[]uint: - *a = make([]uint, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = uint(pu[i]) + if len(*a) == 0 { + *a = make([]uint, cnt) + } else { + i = len(*a) + var tmp []uint + tmp, *a = *a, make([]uint, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = uint(pu[j]) } case *[]int16: - *a = make([]int16, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = int16(pi[i]) + if len(*a) == 0 { + *a = make([]int16, cnt) + } else { + i = len(*a) + var tmp []int16 + tmp, *a = *a, make([]int16, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = int16(pi[j]) } case *[]uint16: - *a = make([]uint16, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = uint16(pu[i]) + if len(*a) == 0 { + *a = make([]uint16, cnt) + } else { + i = len(*a) + var tmp []uint16 + tmp, *a = *a, make([]uint16, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = uint16(pu[j]) } case *[]int32: - *a = make([]int32, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = int32(pi[i]) + if len(*a) == 0 { + *a = make([]int32, cnt) + } else { + i = len(*a) + var tmp []int32 + tmp, *a = *a, make([]int32, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = int32(pi[j]) } case *[]uint32: - *a = make([]uint32, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = uint32(pu[i]) + if len(*a) == 0 { + *a = make([]uint32, cnt) + } else { + i = len(*a) + var tmp []uint32 + tmp, *a = *a, make([]uint32, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = uint32(pu[j]) } case *[]int8: - *a = make([]int8, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = int8(pi[i]) + if len(*a) == 0 { + *a = make([]int8, cnt) + } else { + i = len(*a) + var tmp []int8 + tmp, *a = *a, make([]int8, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = int8(pi[j]) } case *[]uint8: - *a = make([]uint8, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = uint8(pu[i]) + if len(*a) == 0 { + *a = make([]uint8, cnt) + } else { + i = len(*a) + var tmp []uint8 + tmp, *a = *a, make([]uint8, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = uint8(pu[j]) } case *[]bool: - *a = make([]bool, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = bool(pi[i] != 0) + if len(*a) == 0 { + *a = make([]bool, cnt) + } else { + i = len(*a) + var tmp []bool + tmp, *a = *a, make([]bool, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = bool(pi[j] != 0) } default: - slice := reflect.MakeSlice(v.Type(), cnt, cnt) + var slice reflect.Value + if v.Len() == 0 { + slice = reflect.MakeSlice(v.Type(), cnt, cnt) + } else { + i = v.Len() + slice = reflect.Append(v, reflect.MakeSlice(v.Type(), cnt, cnt)) + } switch v.Type().Elem().Kind() { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - for i := 0; i < cnt; i++ { + for j := 0; j < cnt; i, j = i+1, j+1 { sv := slice.Index(i) if sv.Type().Kind() == reflect.Ptr { el := reflect.New(reflect.New(sv.Type().Elem()).Elem().Type()) - el.Elem().SetUint(uint64(pu[i])) + el.Elem().SetUint(uint64(pu[j])) sv.Set(el) } else { - sv.SetUint(uint64(pu[i])) + sv.SetUint(uint64(pu[j])) } } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - for i := 0; i < cnt; i++ { + for j := 0; j < cnt; i, j = i+1, j+1 { sv := slice.Index(i) if sv.Type().Kind() == reflect.Ptr { el := reflect.New(reflect.New(sv.Type().Elem()).Elem().Type()) - el.Elem().SetInt(int64(pi[i])) + el.Elem().SetInt(int64(pi[j])) sv.Set(el) } else { - sv.SetInt(int64(pi[i])) + sv.SetInt(int64(pi[j])) } } default: - panic(fmt.Errorf("Can't set []int to []%s", v.Type().Elem().Kind().String())) + panic(fmt.Errorf("can not convert '[]%s' to '[]int'", v.Type().Elem().Kind().String())) } v.Set(slice) } case valueInt64: switch a := v.Addr().Interface().(type) { case *[]int64: - pi := (*[1 << 27]int64)(ptr)[:l:l] - *a = make([]int64, cnt, cnt) - copy(*a, pi) + pi := (*[1 << 27]int64)(ptr)[:cnt:cnt] + if len(*a) == 0 { + *a = make([]int64, cnt) + copy(*a, pi) + } else { + *a = append(*a, pi...) + } case *[]uint64: - pi := (*[1 << 27]uint64)(ptr)[:l:l] - *a = make([]uint64, cnt, cnt) - copy(*a, pi) + pi := (*[1 << 27]uint64)(ptr)[:cnt:cnt] + if len(*a) == 0 { + *a = make([]uint64, cnt) + copy(*a, pi) + } else { + *a = append(*a, pi...) + } case *[]int: - pi := (*[1 << 27]int64)(ptr)[:l:l] - *a = make([]int, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = int(pi[i]) + pi := (*[1 << 27]int64)(ptr)[:cnt:cnt] + i := len(*a) + if i == 0 { + *a = make([]int, cnt) + } else { + var tmp []int + tmp, *a = *a, make([]int, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = int(pi[j]) } case *[]uint: - pi := (*[1 << 27]uint64)(ptr)[:l:l] - *a = make([]uint, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = uint(pi[i]) + pi := (*[1 << 27]uint64)(ptr)[:cnt] + i := len(*a) + if i == 0 { + *a = make([]uint, cnt) + } else { + var tmp []uint + tmp, *a = *a, make([]uint, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = uint(pi[j]) } default: - slice := reflect.MakeSlice(v.Type(), cnt, cnt) + var slice reflect.Value + i := v.Len() + if i == 0 { + slice = reflect.MakeSlice(v.Type(), cnt, cnt) + } else { + slice = reflect.Append(v, reflect.MakeSlice(v.Type(), cnt, cnt)) + } switch v.Type().Elem().Kind() { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - pi := (*[1 << 27]uint64)(ptr)[:l:l] - for i := 0; i < cnt; i++ { + pi := (*[1 << 27]uint64)(ptr)[:cnt:cnt] + for j := 0; j < cnt; i, j = i+1, j+1 { sv := slice.Index(i) if sv.Type().Kind() == reflect.Ptr { el := reflect.New(reflect.New(sv.Type().Elem()).Elem().Type()) - el.Elem().SetUint(uint64(pi[i])) + el.Elem().SetUint(uint64(pi[j])) sv.Set(el) } else { - sv.SetUint(uint64(pi[i])) + sv.SetUint(uint64(pi[j])) } } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - pi := (*[1 << 27]int64)(ptr)[:l:l] - for i := 0; i < cnt; i++ { + pi := (*[1 << 27]int64)(ptr)[:cnt:cnt] + for j := 0; j < cnt; i, j = i+1, j+1 { sv := slice.Index(i) if sv.Type().Kind() == reflect.Ptr { el := reflect.New(reflect.New(sv.Type().Elem()).Elem().Type()) - el.Elem().SetInt(int64(pi[i])) + el.Elem().SetInt(int64(pi[j])) sv.Set(el) } else { - sv.SetInt(int64(pi[i])) + sv.SetInt(int64(pi[j])) } } default: - panic(fmt.Errorf("Can't set []int64 to []%s", v.Type().Elem().Kind().String())) + panic(fmt.Errorf("can not convert '[]%s' to '[]int64'", v.Type().Elem().Kind().String())) } v.Set(slice) } case valueDouble: - pi := (*[1 << 27]Cdouble)(ptr)[:l:l] + pi := (*[1 << 27]Cdouble)(ptr)[:cnt:cnt] if v.Kind() == reflect.Array { if v.Len() < cnt { - panic(fmt.Errorf("Can't set %d values to array of %d elements", cnt, v.Len())) + panic(fmt.Errorf("can not set %d values to array of %d elements", cnt, v.Len())) } switch v.Type().Elem().Kind() { case reflect.Float32: - for i := 0; i < cnt; i++ { + for i = 0; i < cnt; i++ { v.Index(i).SetFloat(float64(float32(pi[i]))) } case reflect.Float64: - for i := 0; i < cnt; i++ { + for i = 0; i < cnt; i++ { v.Index(i).SetFloat(float64(pi[i])) } default: - panic(fmt.Errorf("Can't set []double to []%s", v.Type().Elem().Kind().String())) + panic(fmt.Errorf("can not convert '[]%s' to '[]double'", v.Type().Elem().Kind().String())) } } else { switch a := v.Addr().Interface().(type) { case *[]float64: - *a = make([]float64, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = float64(pi[i]) + if len(*a) == 0 { + *a = make([]float64, cnt) + } else { + i = len(*a) + var tmp []float64 + tmp, *a = *a, make([]float64, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = float64(pi[j]) } case *[]float32: - *a = make([]float32, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = float32(pi[i]) + if len(*a) == 0 { + *a = make([]float32, cnt) + } else { + i = len(*a) + var tmp []float32 + tmp, *a = *a, make([]float32, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = float32(pi[j]) } default: - slice := reflect.MakeSlice(v.Type(), cnt, cnt) - for i := 0; i < cnt; i++ { + var slice reflect.Value + if v.Len() == 0 { + slice = reflect.MakeSlice(v.Type(), cnt, cnt) + } else { + i = v.Len() + slice = reflect.Append(v, reflect.MakeSlice(v.Type(), cnt, cnt)) + } + for j := 0; j < cnt; i, j = i+1, j+1 { sv := slice.Index(i) if sv.Type().Kind() == reflect.Ptr { el := reflect.New(reflect.New(sv.Type().Elem()).Elem().Type()) - el.Elem().SetFloat(float64(pi[i])) + el.Elem().SetFloat(float64(pi[j])) sv.Set(el) } else { - sv.SetFloat(float64(pi[i])) + sv.SetFloat(float64(pi[j])) } } v.Set(slice) } } case valueBool: - pb := (*[1 << 27]Cbool)(ptr)[:l:l] + pb := (*[1 << 27]Cbool)(ptr)[:cnt:cnt] switch a := v.Addr().Interface().(type) { case *[]bool: - *a = make([]bool, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = bool(pb[i] != 0) + if len(*a) == 0 { + *a = make([]bool, cnt) + } else { + i = len(*a) + var tmp []bool + tmp, *a = *a, make([]bool, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = bool(pb[j] != 0) } default: - slice := reflect.MakeSlice(v.Type(), cnt, cnt) - for i := 0; i < cnt; i++ { + var slice reflect.Value + if v.Len() == 0 { + slice = reflect.MakeSlice(v.Type(), cnt, cnt) + } else { + i = v.Len() + slice = reflect.Append(v, reflect.MakeSlice(v.Type(), cnt, cnt)) + } + for j := 0; j < cnt; i, j = i+1, j+1 { sv := slice.Index(i) if sv.Type().Kind() == reflect.Ptr { el := reflect.New(reflect.New(sv.Type().Elem()).Elem().Type()) - el.Elem().SetBool(bool(pb[i] != 0)) + el.Elem().SetBool(bool(pb[j] != 0)) sv.Set(el) } else { - sv.SetBool(bool(pb[i] != 0)) + sv.SetBool(bool(pb[j] != 0)) } } v.Set(slice) } case valueString: if a, ok := v.Addr().Interface().(*[]string); ok { - *a = make([]string, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = pl.getString(field, i+startIdx) + if len(*a) == 0 { + *a = make([]string, cnt) + } else { + i = len(*a) + var tmp []string + tmp, *a = *a, make([]string, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = pl.getString(field, j+startIdx) } } else { - slice := reflect.MakeSlice(v.Type(), cnt, cnt) - for i := 0; i < cnt; i++ { - s := pl.getString(field, i+startIdx) + var slice reflect.Value + if v.Len() == 0 { + slice = reflect.MakeSlice(v.Type(), cnt, cnt) + } else { + i = v.Len() + slice = reflect.Append(v, reflect.MakeSlice(v.Type(), cnt, cnt)) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + s := pl.getString(field, j+startIdx) sv := slice.Index(i) if sv.Type().Kind() == reflect.Ptr { el := reflect.New(reflect.New(sv.Type().Elem()).Elem().Type()) @@ -465,28 +618,41 @@ func (pl *payloadIface) getArray(field int, startIdx int, cnt int, v reflect.Val v.Set(slice) } case valueUuid: - pi := (*[1 << 27]uint64)(ptr)[:l * 2:l * 2] + pi := (*[1 << 27]uint64)(ptr)[: l*2 : l*2] if a, ok := v.Addr().Interface().(*[]string); ok { - *a = make([]string, cnt, cnt) - for i := 0; i < cnt; i++ { - (*a)[i] = createUuid([2]uint64{pi[i * 2], pi[i * 2 + 1]}) + if len(*a) == 0 { + *a = make([]string, cnt) + } else { + i = len(*a) + var tmp []string + tmp, *a = *a, make([]string, len(*a)+cnt) + copy(*a, tmp) + } + for j := 0; j < cnt; i, j = i+1, j+1 { + (*a)[i] = createUuid([2]uint64{pi[j*2], pi[j*2+1]}) } } else { - slice := reflect.MakeSlice(v.Type(), cnt, cnt) - for i := 0; i < cnt; i++ { + var slice reflect.Value + if v.Len() == 0 { + slice = reflect.MakeSlice(v.Type(), cnt, cnt) + } else { + i = v.Len() + slice = reflect.Append(v, reflect.MakeSlice(v.Type(), cnt, cnt)) + } + for j := 0; j < cnt; i, j = i+1, j+1 { sv := slice.Index(i) if sv.Type().Kind() == reflect.Ptr { el := reflect.New(reflect.New(sv.Type().Elem()).Elem().Type()) - el.Elem().SetString(createUuid([2]uint64{pi[i * 2], pi[i * 2 + 1]})) + el.Elem().SetString(createUuid([2]uint64{pi[j*2], pi[j*2+1]})) sv.Set(el) } else { - sv.SetString(createUuid([2]uint64{pi[i * 2], pi[i * 2 + 1]})) + sv.SetString(createUuid([2]uint64{pi[j*2], pi[j*2+1]})) } } v.Set(slice) } default: - panic(fmt.Errorf("Got C array with elements of unknown C type %d in field '%s' for go type '%s'", pl.t.Fields[field].Type, pl.t.Fields[field].Name, v.Type().Elem().Kind().String())) + panic(fmt.Errorf("got C array with elements of unknown C type %d in field '%s' for go type '%s'", pl.t.Fields[field].Type, pl.t.Fields[field].Name, v.Type().Elem().Kind().String())) } } diff --git a/cjson/decoder.go b/cjson/decoder.go index d830c5fc7..ee28fe303 100644 --- a/cjson/decoder.go +++ b/cjson/decoder.go @@ -121,7 +121,7 @@ func skipTag(rdser *Serializer, tagType int) { case TAG_UUID: rdser.GetUuid() default: - panic(fmt.Errorf("Can't skip tagType %s", tagTypeName(tagType))) + panic(fmt.Errorf("can not skip tagType '%s'", tagTypeName(tagType))) } } @@ -134,7 +134,7 @@ func asInt(rdser *Serializer, tagType int) int64 { case TAG_DOUBLE: return int64(rdser.GetDouble()) default: - panic(fmt.Errorf("Can't convert tagType %s to int", tagTypeName(tagType))) + panic(fmt.Errorf("can not convert tagType '%s' to 'int'", tagTypeName(tagType))) } } @@ -145,7 +145,7 @@ func asFloat(rdser *Serializer, tagType int) float64 { case TAG_DOUBLE: return rdser.GetDouble() default: - panic(fmt.Errorf("Can't convert tagType %s to float", tagTypeName(tagType))) + panic(fmt.Errorf("can not convert tagType '%s' to 'float'", tagTypeName(tagType))) } } @@ -156,7 +156,7 @@ func asString(rdser *Serializer, tagType int) string { case TAG_UUID: return rdser.GetUuid() default: - panic(fmt.Errorf("Can't convert tagType %s to string", tagTypeName(tagType))) + panic(fmt.Errorf("can not convert tagType '%s' to 'string'", tagTypeName(tagType))) } } @@ -183,43 +183,105 @@ func asIface(rdser *Serializer, tagType int) interface{} { case TAG_UUID: return rdser.GetUuid() default: - panic(fmt.Errorf("Can't convert tagType %s to iface", tagTypeName(tagType))) + panic(fmt.Errorf("can not convert tagType '%s' to 'interface'", tagTypeName(tagType))) } } -func mkSlice(v *reflect.Value, count int) { +func mkSlice(v *reflect.Value, count int) (offset int) { + offset = v.Len() switch a := v.Addr().Interface().(type) { case *[]string: - *a = make([]string, count, count) + if offset == 0 { + *a = make([]string, count) + } else { + *a = append(*a, make([]string, count)...) + } case *[]int: - *a = make([]int, count, count) + if offset == 0 { + *a = make([]int, count) + } else { + *a = append(*a, make([]int, count)...) + } case *[]int64: - *a = make([]int64, count, count) + if offset == 0 { + *a = make([]int64, count) + } else { + *a = append(*a, make([]int64, count)...) + } case *[]int32: - *a = make([]int32, count, count) + if offset == 0 { + *a = make([]int32, count) + } else { + *a = append(*a, make([]int32, count)...) + } case *[]int16: - *a = make([]int16, count, count) + if offset == 0 { + *a = make([]int16, count) + } else { + *a = append(*a, make([]int16, count)...) + } case *[]int8: - *a = make([]int8, count, count) + if offset == 0 { + *a = make([]int8, count) + } else { + *a = append(*a, make([]int8, count)...) + } case *[]uint: - *a = make([]uint, count, count) + if offset == 0 { + *a = make([]uint, count) + } else { + *a = append(*a, make([]uint, count)...) + } case *[]uint64: - *a = make([]uint64, count, count) + if offset == 0 { + *a = make([]uint64, count) + } else { + *a = append(*a, make([]uint64, count)...) + } case *[]uint32: - *a = make([]uint32, count, count) + if offset == 0 { + *a = make([]uint32, count) + } else { + *a = append(*a, make([]uint32, count)...) + } case *[]uint16: - *a = make([]uint16, count, count) + if offset == 0 { + *a = make([]uint16, count) + } else { + *a = append(*a, make([]uint16, count)...) + } case *[]uint8: - *a = make([]uint8, count, count) + if offset == 0 { + *a = make([]uint8, count) + } else { + *a = append(*a, make([]uint8, count)...) + } case *[]float64: - *a = make([]float64, count, count) + if offset == 0 { + *a = make([]float64, count) + } else { + *a = append(*a, make([]float64, count)...) + } case *[]float32: - *a = make([]float32, count, count) + if offset == 0 { + *a = make([]float32, count) + } else { + *a = append(*a, make([]float32, count)...) + } case *[]bool: - *a = make([]bool, count, count) + if offset == 0 { + *a = make([]bool, count) + } else { + *a = append(*a, make([]bool, count)...) + } default: - v.Set(reflect.MakeSlice(v.Type(), count, count)) + if offset == 0 { + v.Set(reflect.MakeSlice(v.Type(), count, count)) + } else { + v.Set(reflect.AppendSlice(*v, reflect.MakeSlice(v.Type(), count, count))) + } } + return } func mkValue(ctagType int) (v reflect.Value) { @@ -237,7 +299,7 @@ func mkValue(ctagType int) (v reflect.Value) { case TAG_ARRAY: v = reflect.New(ifaceSliceType).Elem() default: - panic(fmt.Errorf("Invalid ctagType=%d", ctagType)) + panic(fmt.Errorf("invalid ctagType=%d", ctagType)) } return v } @@ -251,22 +313,25 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. var ptr unsafe.Pointer k := v.Kind() + offset := 0 switch k { case reflect.Slice: - mkSlice(v, count) + offset = mkSlice(v, count) ptr = unsafe.Pointer(v.Pointer()) case reflect.Interface: origV = *v *v = reflect.ValueOf(reflect.New(ifaceSliceType).Interface()).Elem() - mkSlice(v, count) + offset = mkSlice(v, count) ptr = unsafe.Pointer(v.Pointer()) case reflect.Array: if v.Len() < count { - panic(fmt.Errorf("Array bounds overflow need %d, len=%d", count, v.Len())) + panic(fmt.Errorf("array bounds overflow. Required %d, but array len is %d", count, v.Len())) } ptr = unsafe.Pointer(v.Index(0).Addr().Pointer()) + // offset is 0 + // No concatenation for the fixed size arrays default: - panic(fmt.Errorf("Can't set array to %s", v.Type().Kind().String())) + panic(fmt.Errorf("can not convert '%s' to 'array'", v.Type().Kind().String())) } if subtag != TAG_OBJECT { @@ -279,12 +344,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. switch k { case reflect.Int: if !isPtr { - sl := (*[1 << 28]int)(ptr)[:count:count] + sl := (*[1 << 28]int)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = int(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*int)(ptr)[:count:count] + sl := (*[1 << 28]*int)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := int(asInt(rdser, subtag)) sl[i] = &u @@ -292,12 +357,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Uint: if !isPtr { - sl := (*[1 << 28]uint)(ptr)[:count:count] + sl := (*[1 << 28]uint)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = uint(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*uint)(ptr)[:count:count] + sl := (*[1 << 28]*uint)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := uint(asInt(rdser, subtag)) sl[i] = &u @@ -305,12 +370,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Int64: if !isPtr { - sl := (*[1 << 27]int64)(ptr)[:count:count] + sl := (*[1 << 27]int64)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = int64(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*int64)(ptr)[:count:count] + sl := (*[1 << 28]*int64)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := int64(asInt(rdser, subtag)) sl[i] = &u @@ -318,12 +383,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Uint64: if !isPtr { - sl := (*[1 << 27]uint64)(ptr)[:count:count] + sl := (*[1 << 27]uint64)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = uint64(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*uint64)(ptr)[:count:count] + sl := (*[1 << 28]*uint64)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := uint64(asInt(rdser, subtag)) sl[i] = &u @@ -331,12 +396,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Int32: if !isPtr { - sl := (*[1 << 28]int32)(ptr)[:count:count] + sl := (*[1 << 28]int32)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = int32(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*int32)(ptr)[:count:count] + sl := (*[1 << 28]*int32)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := int32(asInt(rdser, subtag)) sl[i] = &u @@ -344,12 +409,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Uint32: if !isPtr { - sl := (*[1 << 28]uint32)(ptr)[:count:count] + sl := (*[1 << 28]uint32)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = uint32(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*uint32)(ptr)[:count:count] + sl := (*[1 << 28]*uint32)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := uint32(asInt(rdser, subtag)) sl[i] = &u @@ -357,12 +422,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Int16: if !isPtr { - sl := (*[1 << 29]int16)(ptr)[:count:count] + sl := (*[1 << 29]int16)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = int16(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*int16)(ptr)[:count:count] + sl := (*[1 << 28]*int16)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := int16(asInt(rdser, subtag)) sl[i] = &u @@ -370,12 +435,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Uint16: if !isPtr { - sl := (*[1 << 29]uint16)(ptr)[:count:count] + sl := (*[1 << 29]uint16)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = uint16(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*uint16)(ptr)[:count:count] + sl := (*[1 << 28]*uint16)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := uint16(asInt(rdser, subtag)) sl[i] = &u @@ -383,12 +448,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Int8: if !isPtr { - sl := (*[1 << 30]int8)(ptr)[:count:count] + sl := (*[1 << 30]int8)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = int8(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*int8)(ptr)[:count:count] + sl := (*[1 << 28]*int8)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := int8(asInt(rdser, subtag)) sl[i] = &u @@ -396,12 +461,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Uint8: if !isPtr { - sl := (*[1 << 30]uint8)(ptr)[:count:count] + sl := (*[1 << 30]uint8)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = uint8(asInt(rdser, subtag)) } } else { - sl := (*[1 << 28]*uint8)(ptr)[:count:count] + sl := (*[1 << 28]*uint8)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { u := uint8(asInt(rdser, subtag)) sl[i] = &u @@ -409,12 +474,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Float32: if !isPtr { - sl := (*[1 << 28]float32)(ptr)[:count:count] + sl := (*[1 << 28]float32)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = float32(asFloat(rdser, subtag)) } } else { - sl := (*[1 << 28]*float32)(ptr)[:count:count] + sl := (*[1 << 28]*float32)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { f := float32(asFloat(rdser, subtag)) sl[i] = &f @@ -422,12 +487,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Float64: if !isPtr { - sl := (*[1 << 27]float64)(ptr)[:count:count] + sl := (*[1 << 27]float64)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = asFloat(rdser, subtag) } } else { - sl := (*[1 << 28]*float64)(ptr)[:count:count] + sl := (*[1 << 28]*float64)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { f := asFloat(rdser, subtag) sl[i] = &f @@ -435,12 +500,12 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.Bool: if !isPtr { - sl := (*[1 << 27]bool)(ptr)[:count:count] + sl := (*[1 << 27]bool)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = rdser.GetVarUInt() != 0 } } else { - sl := (*[1 << 28]*bool)(ptr)[:count:count] + sl := (*[1 << 28]*bool)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { b := rdser.GetVarUInt() != 0 sl[i] = &b @@ -448,27 +513,27 @@ func (dec *Decoder) decodeSlice(pl *payloadIface, rdser *Serializer, v *reflect. } case reflect.String: if !isPtr { - sl := (*[1 << 27]string)(ptr)[:count:count] + sl := (*[1 << 27]string)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = asString(rdser, subtag) } } else { - sl := (*[1 << 28]*string)(ptr)[:count:count] + sl := (*[1 << 28]*string)(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { s := asString(rdser, subtag) sl[i] = &s } } case reflect.Interface: - sl := (*[1 << 27]interface{})(ptr)[:count:count] + sl := (*[1 << 27]interface{})(ptr)[offset : offset+count : offset+count] for i := 0; i < count; i++ { sl[i] = asIface(rdser, subtag) } default: - panic(fmt.Errorf("Internal error - can't decode array of type %s", v.Type().Elem().Kind().String())) + panic(fmt.Errorf("internal error - can't decode array of type %s", v.Type().Elem().Kind().String())) } } else { - for i := 0; i < count; i++ { + for i := offset; i < offset+count; i++ { dec.decodeValue(pl, rdser, v.Index(i), fieldsoutcnt, cctagsPath) } } @@ -552,7 +617,7 @@ func (dec *Decoder) decodeValue(pl *payloadIface, rdser *Serializer, v reflect.V return dec.skipStruct(pl, rdser, fieldsoutcnt, ctag) } } else { - panic(fmt.Errorf("Err: intf=%s, name='%s' %s", v.Type().Name(), dec.state.tagsMatcher.tag2name(ctagName), ctag.Dump())) + panic(fmt.Errorf("err: intf=%s, name='%s' %s", v.Type().Name(), dec.state.tagsMatcher.tag2name(ctagName), ctag.Dump())) } k = v.Kind() if k == reflect.Ptr { @@ -597,20 +662,50 @@ func (dec *Decoder) decodeValue(pl *payloadIface, rdser *Serializer, v reflect.V case k == reflect.String: v.SetString(str) case k == reflect.Slice, k == reflect.Array: - b, e := base64.StdEncoding.DecodeString(str) - if e != nil { - panic(fmt.Errorf("Can't base64 decode %s", str)) + elemK := v.Type().Elem().Kind() + if elemK == reflect.String { + if k == reflect.Slice { + el := reflect.New(v.Type().Elem()).Elem() + el.SetString(str) + extSlice := reflect.Append(v, el) + v.Set(extSlice) + } else { + panic(fmt.Errorf("can not put single value into the fixed size array of strings '%s'", str)) + } + } else if elemK == reflect.Interface { + if k == reflect.Slice { + el := reflect.New(v.Type().Elem()).Elem() + el.Set(reflect.ValueOf(str)) + extSlice := reflect.Append(v, el) + v.Set(extSlice) + } else { + panic(fmt.Errorf("can not put single value into the fixed size array of interfaces '%s'", str)) + } + } else { + b, e := base64.StdEncoding.DecodeString(str) + if e != nil { + panic(fmt.Errorf("can not decode base64 '%s': %v", str, e)) + } + v.SetBytes(b) } - v.SetBytes(b) case k == reflect.Interface: v.Set(reflect.ValueOf(str)) case k == reflect.Struct && v.Type().String() == "time.Time": tm, _ := time.Parse(time.RFC3339Nano, str) v.Set(reflect.ValueOf(tm)) default: - panic(fmt.Errorf("Can't set string to %s", v.Type().Kind().String())) + panic(fmt.Errorf("can not convert '%s' to 'string'", v.Type().Kind().String())) } default: + if k == reflect.Slice { + el := reflect.New(v.Type().Elem()).Elem() + extSlice := reflect.Append(v, el) + v.Set(extSlice) + v = v.Index(v.Len() - 1) + k = v.Type().Kind() + } else if k == reflect.Array { + panic(fmt.Errorf("can not put single value into the fixed size array")) + } switch k { case reflect.Float32, reflect.Float64: v.SetFloat(asFloat(rdser, ctagType)) @@ -641,7 +736,7 @@ func (dec *Decoder) decodeValue(pl *payloadIface, rdser *Serializer, v reflect.V case reflect.String: mv.SetMapIndex(reflect.ValueOf(name), v) default: - panic(fmt.Errorf("Unsuported map key type %s", mv.Type().Key().Kind().String())) + panic(fmt.Errorf("unsuported map key type '%s'", mv.Type().Key().Kind().String())) } } @@ -662,7 +757,7 @@ func (dec *Decoder) DecodeCPtr(cptr uintptr, dest interface{}) (err error) { if ret := recover(); ret != nil { if dec.loggerOwner != nil { if logger := dec.loggerOwner.GetLogger(); logger != nil { - logger.Printf(1, + logger.Printf(bindings.ERROR, "Interface: %#v\nRead position: %d\nTags(v%d): %v\nPayload Type: %+v\nPayload Value: %v\nTags cache: %+v\nData dump:\n%s\nError: %v\nTagsMatcher: { state_token: 0x%08X, version: %d }\n", dest, ser.Pos(), @@ -678,7 +773,12 @@ func (dec *Decoder) DecodeCPtr(cptr uintptr, dest interface{}) (err error) { ) } } - err = ret.(error) + switch v := ret.(type) { + case error: + err = v + default: + err = fmt.Errorf("rq: DecodeCPtr error: %v", ret) + } } }() @@ -687,7 +787,7 @@ func (dec *Decoder) DecodeCPtr(cptr uintptr, dest interface{}) (err error) { dec.decodeValue(pl, ser, reflect.ValueOf(dest), fieldsoutcnt, ctagsPath) if !ser.Eof() { - panic(fmt.Errorf("Internal error - left unparsed data")) + panic(fmt.Errorf("internal error - left unparsed data")) } return err } @@ -703,7 +803,7 @@ func (dec *Decoder) Decode(cjson []byte, dest interface{}) (err error) { if ret := recover(); ret != nil { if dec.loggerOwner != nil { if logger := dec.loggerOwner.GetLogger(); logger != nil { - logger.Printf(1, + logger.Printf(bindings.ERROR, "Interface: %#v\nRead position: %d\nTags(v%d): %v\nTags cache: %+v\nData dump:\n%s\nError: %v\nTagsMatcher: { state_token: 0x%08X, version: %d }\n", dest, ser.Pos(), @@ -717,7 +817,12 @@ func (dec *Decoder) Decode(cjson []byte, dest interface{}) (err error) { ) } } - err = ret.(error) + switch v := ret.(type) { + case error: + err = v + default: + err = fmt.Errorf("rq: Decode error: %v", ret) + } } }() diff --git a/cpp_src/CMakeLists.txt b/cpp_src/CMakeLists.txt index 8bfc3150d..c47953a94 100644 --- a/cpp_src/CMakeLists.txt +++ b/cpp_src/CMakeLists.txt @@ -53,25 +53,28 @@ include (TargetArch) target_architecture(COMPILER_TARGET_ARCH) # Configure compile options -string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") -string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") -string(REPLACE "-O2" "-O3" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") -if (NOT ${COMPILER_TARGET_ARCH} STREQUAL "e2k") - string(REPLACE "-g" "-g1" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") -else() - string(REPLACE "-g" "-g0" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") -endif() - +if (MSVC) + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g1") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g1") + set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") + set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG") +else () + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g1") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -g1") + set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") + set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") +endif () if (${COMPILER_TARGET_ARCH} STREQUAL "e2k") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g0") add_definitions(-D__E2K__) add_definitions(-D__LCC__) -endif() +endif () if (NOT MSVC AND NOT APPLE) check_linker_flag (-gz cxx_linker_supports_gz) if (cxx_linker_supports_gz) - set (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -gz") - endif () + set (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -gz") + endif () endif () if (MSVC) diff --git a/cpp_src/client/coroqueryresults.cc b/cpp_src/client/coroqueryresults.cc index fdc295c75..ee3c1649a 100644 --- a/cpp_src/client/coroqueryresults.cc +++ b/cpp_src/client/coroqueryresults.cc @@ -212,9 +212,10 @@ Item CoroQueryResults::Iterator::GetItem() { if (err.ok()) { return item; } + return Item(); } catch (const Error &) { + return Item(); } - return Item(); } int64_t CoroQueryResults::Iterator::GetLSN() { diff --git a/cpp_src/client/cororpcclient.cc b/cpp_src/client/cororpcclient.cc index feb8cbb00..14db8e97a 100644 --- a/cpp_src/client/cororpcclient.cc +++ b/cpp_src/client/cororpcclient.cc @@ -158,7 +158,7 @@ Error CoroRPCClient::modifyItem(std::string_view nsName, Item& item, int mode, s } CoroQueryResults qr; InternalRdxContext ctxCompl = ctx.WithCompletion(nullptr); - auto ret = selectImpl(Query(std::string(nsName)).Limit(0), qr, netTimeout, ctxCompl); + auto ret = selectImpl(Query(nsName).Limit(0), qr, netTimeout, ctxCompl); if (ret.code() == errTimeout) { return Error(errTimeout, "Request timeout"); } @@ -242,7 +242,7 @@ Error CoroRPCClient::Delete(const Query& query, CoroQueryResults& result, const query.Serialize(ser); NsArray nsArray; - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); result = CoroQueryResults(&conn_, std::move(nsArray), 0, config_.FetchAmount, config_.RequestTimeout); @@ -263,7 +263,7 @@ Error CoroRPCClient::Update(const Query& query, CoroQueryResults& result, const query.Serialize(ser); NsArray nsArray; - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); result = CoroQueryResults(&conn_, std::move(nsArray), 0, config_.FetchAmount, config_.RequestTimeout); @@ -313,10 +313,10 @@ Error CoroRPCClient::selectImpl(const Query& query, CoroQueryResults& result, se WrSerializer qser, pser; int flags = result.fetchFlags_ ? result.fetchFlags_ : (kResultsWithPayloadTypes | kResultsCJson); flags |= kResultsSupportIdleTimeout; - bool hasJoins = !query.joinQueries_.empty(); + bool hasJoins = !query.GetJoinQueries().empty(); if (!hasJoins) { - for (auto& mq : query.mergeQueries_) { - if (!mq.joinQueries_.empty()) { + for (auto& mq : query.GetMergeQueries()) { + if (!mq.GetJoinQueries().empty()) { hasJoins = true; break; } @@ -328,7 +328,7 @@ Error CoroRPCClient::selectImpl(const Query& query, CoroQueryResults& result, se } NsArray nsArray; query.Serialize(qser); - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); h_vector vers; for (auto& ns : nsArray) { vers.push_back(ns->tagsMatcher_.version() ^ ns->tagsMatcher_.stateToken()); diff --git a/cpp_src/client/queryresults.cc b/cpp_src/client/queryresults.cc index 83b1755c3..639d4cbab 100644 --- a/cpp_src/client/queryresults.cc +++ b/cpp_src/client/queryresults.cc @@ -250,9 +250,10 @@ Item QueryResults::Iterator::GetItem() { if (err.ok()) { return item; } + return Item(); } catch (const Error &) { + return Item(); } - return Item(); } int64_t QueryResults::Iterator::GetLSN() { diff --git a/cpp_src/client/resultserializer.cc b/cpp_src/client/resultserializer.cc index cc23e0be8..e6cb75c3e 100644 --- a/cpp_src/client/resultserializer.cc +++ b/cpp_src/client/resultserializer.cc @@ -50,6 +50,8 @@ void ResultSerializer::GetRawQueryParams(ResultSerializer::QueryParams& ret, con case QueryResultExplain: ret.explainResults = std::string(data); break; + default: + throw Error(errLogic, "Unexpected Query tag: %d", tag); } } } diff --git a/cpp_src/client/rpcclient.cc b/cpp_src/client/rpcclient.cc index f0f4b4b72..b747ea90d 100644 --- a/cpp_src/client/rpcclient.cc +++ b/cpp_src/client/rpcclient.cc @@ -3,6 +3,7 @@ #include #include "client/itemimpl.h" #include "core/namespacedef.h" +#include "core/schema.h" #include "gason/gason.h" #include "tools/cpucheck.h" #include "tools/errors.h" @@ -98,6 +99,7 @@ void RPCClient::run(size_t thIdx) { workers_[thIdx].stop_.start(); delayedUpdates_.clear(); + serialDelays_ = 0; for (size_t i = thIdx; int(i) < config_.ConnPoolSize; i += config_.WorkerThreads) { connections_[i].reset(new cproto::ClientConnection(workers_[thIdx].loop_, &connectData_, @@ -381,7 +383,7 @@ Error RPCClient::Delete(const Query& query, QueryResults& result, const Internal auto conn = getConn(); NsArray nsArray; - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); result = QueryResults(conn, std::move(nsArray), nullptr, 0, config_.FetchAmount, config_.RequestTimeout); @@ -408,7 +410,7 @@ Error RPCClient::Update(const Query& query, QueryResults& result, const Internal auto conn = getConn(); NsArray nsArray; - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); result = QueryResults(conn, std::move(nsArray), nullptr, 0, config_.FetchAmount, config_.RequestTimeout); @@ -469,10 +471,10 @@ Error RPCClient::selectImpl(const Query& query, QueryResults& result, cproto::Cl const InternalRdxContext& ctx) { WrSerializer qser, pser; int flags = result.fetchFlags_ ? result.fetchFlags_ : (kResultsWithPayloadTypes | kResultsCJson); - bool hasJoins = !query.joinQueries_.empty(); + bool hasJoins = !query.GetJoinQueries().empty(); if (!hasJoins) { - for (auto& mq : query.mergeQueries_) { - if (!mq.joinQueries_.empty()) { + for (auto& mq : query.GetMergeQueries()) { + if (!mq.GetJoinQueries().empty()) { hasJoins = true; break; } @@ -484,7 +486,7 @@ Error RPCClient::selectImpl(const Query& query, QueryResults& result, cproto::Cl } NsArray nsArray; query.Serialize(qser); - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); h_vector vers; for (auto& ns : nsArray) { shared_lock lck(ns->lck_); @@ -717,21 +719,39 @@ void RPCClient::onUpdates(net::cproto::RPCAnswer& ans, cproto::ClientConnection* // If tagsMatcher has been updated but there is no bundled tagsMatcher in cjson // then we need to ask server to send tagsMatcher. + ++serialDelays_; // Delay this update and all the further updates until we get responce from server. ans.EnsureHold(); delayedUpdates_.emplace_back(std::move(ans)); QueryResults* qr = new QueryResults; Select(Query(std::string(nsName)).Limit(0), *qr, - InternalRdxContext(nullptr, - [=](const Error& err) { - delete qr; - // If there are delayed updates then send them to client - auto uq = std::move(delayedUpdates_); - delayedUpdates_.clear(); - if (err.ok()) - for (auto& a1 : uq) onUpdates(a1, conn); - }), + InternalRdxContext( + nullptr, + [this, qr, conn](const Error& err) { + delete qr; + // If there are delayed updates then send them to client + auto uq = std::move(delayedUpdates_); + delayedUpdates_.clear(); + + if (!err.ok() || serialDelays_ > 1) { + // This update was already dealyed, but was not able to synchronize tagsmatcher. + // Such situation usually means, that master's namespace was recreated and must be synchronized via force + // sync. + // Current fix is suboptimal and in some cases even incorrect (but still better, than previous + // implementation) - proper fix requires some versioning info about namespaces, which exists + // in v4 only + std::string_view nsName(std::string_view(uq.front().GetArgs(1)[1])); + logPrintf( + LogWarning, + "[repl:%s] Unable to sync tags matcher via online-replication (err: '%s'). Calling UpdatesLost fallback", + nsName, err.what()); + serialDelays_ = 0; + observers_.OnUpdatesLost(nsName); + } else { + for (auto& a1 : uq) onUpdates(a1, conn); + } + }), conn); return; } else { @@ -748,7 +768,17 @@ void RPCClient::onUpdates(net::cproto::RPCAnswer& ans, cproto::ClientConnection* ns->tagsMatcher_.deserialize(rdser, wrec.itemModify.tmVersion, ns->tagsMatcher_.stateToken()); } } + } else if (wrec.type == WalTagsMatcher) { + TagsMatcher tm; + Serializer ser(wrec.data.data(), wrec.data.size()); + const auto version = ser.GetVarint(); + const auto stateToken = ser.GetVarint(); + tm.deserialize(ser, version, stateToken); + auto ns = getNamespace(nsName); + std::lock_guard lck(ns->lck_); + ns->tagsMatcher_ = std::move(tm); } + serialDelays_ = 0; observers_.OnWALUpdate(LSNPair(lsn, originLSN), nsName, wrec); } diff --git a/cpp_src/client/rpcclient.h b/cpp_src/client/rpcclient.h index eefb2cf03..a906fe898 100644 --- a/cpp_src/client/rpcclient.h +++ b/cpp_src/client/rpcclient.h @@ -90,6 +90,7 @@ class RPCClient { ev::async stop_; std::atomic_bool running; }; + Error selectImpl(std::string_view query, QueryResults &result, cproto::ClientConnection *, seconds netTimeout, const InternalRdxContext &ctx); Error selectImpl(const Query &query, QueryResults &result, cproto::ClientConnection *, seconds netTimeout, @@ -122,6 +123,7 @@ class RPCClient { UpdatesObservers observers_; std::atomic updatesConn_; std::vector delayedUpdates_; + uint64_t serialDelays_ = 0; cproto::ClientConnection::ConnectData connectData_; }; diff --git a/cpp_src/client/rpcclientmock.cc b/cpp_src/client/rpcclientmock.cc index 5c0d4b6ef..546cd0365 100644 --- a/cpp_src/client/rpcclientmock.cc +++ b/cpp_src/client/rpcclientmock.cc @@ -37,7 +37,7 @@ Error RPCClientMock::Delete(const Query& query, QueryResults& result, const Inte auto conn = getConn(); NsArray nsArray; - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); result = QueryResults(conn, std::move(nsArray), nullptr, 0, config_.FetchAmount, config_.RequestTimeout); @@ -69,7 +69,7 @@ Error RPCClientMock::Update(const Query& query, QueryResults& result, const Inte auto conn = getConn(); NsArray nsArray; - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); result = QueryResults(conn, std::move(nsArray), nullptr, 0, config_.FetchAmount, config_.RequestTimeout); @@ -289,10 +289,10 @@ Error RPCClientMock::selectImpl(const Query& query, QueryResults& result, cproto flags = result.fetchFlags_ ? result.fetchFlags_ : (kResultsWithPayloadTypes | kResultsCJson); } - bool hasJoins = !query.joinQueries_.empty(); + bool hasJoins = !query.GetJoinQueries().empty(); if (!hasJoins) { - for (auto& mq : query.mergeQueries_) { - if (!mq.joinQueries_.empty()) { + for (auto& mq : query.GetMergeQueries()) { + if (!mq.GetJoinQueries().empty()) { hasJoins = true; break; } @@ -308,7 +308,7 @@ Error RPCClientMock::selectImpl(const Query& query, QueryResults& result, cproto NsArray nsArray; query.Serialize(qser); - query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); + query.WalkNested(true, true, false, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); }); h_vector vers; for (auto& ns : nsArray) { shared_lock lck(ns->lck_); diff --git a/cpp_src/cmd/reindexer_server/test/test_storage_compatibility.sh b/cpp_src/cmd/reindexer_server/test/test_storage_compatibility.sh new file mode 100755 index 000000000..d189d3841 --- /dev/null +++ b/cpp_src/cmd/reindexer_server/test/test_storage_compatibility.sh @@ -0,0 +1,195 @@ +#!/bin/bash +# Task: https://github.com/restream/reindexer/-/issues/1188 +set -e + +function KillAndRemoveServer { + local pid=$1 + kill $pid + wait $pid + yum remove -y 'reindexer*' > /dev/null +} + +function WaitForDB { + # wait until DB is loaded + set +e # disable "exit on error" so the script won't stop when DB's not loaded yet + is_connected=$(reindexer_tool --dsn $ADDRESS --command '\databases list'); + while [[ $is_connected != "test" ]] + do + sleep 2 + is_connected=$(reindexer_tool --dsn $ADDRESS --command '\databases list'); + done + set -e +} + +function CompareNamespacesLists { + local ns_list_actual=$1 + local ns_list_expected=$2 + local pid=$3 + + diff=$(echo ${ns_list_actual[@]} ${ns_list_expected[@]} | tr ' ' '\n' | sort | uniq -u) # compare in any order + if [ "$diff" == "" ]; then + echo "## PASS: namespaces list not changed" + else + echo "##### FAIL: namespaces list was changed" + echo "expected: $ns_list_expected" + echo "actual: $ns_list_actual" + KillAndRemoveServer $pid; + exit 1 + fi +} + +function CompareMemstats { + local actual=$1 + local expected=$2 + local pid=$3 + diff=$(echo ${actual[@]} ${expected[@]} | tr ' ' '\n' | sed 's/\(.*\),$/\1/' | sort | uniq -u) # compare in any order + if [ "$diff" == "" ]; then + echo "## PASS: memstats not changed" + else + echo "##### FAIL: memstats was changed" + echo "expected: $expected" + echo "actual: $actual" + KillAndRemoveServer $pid; + exit 1 + fi +} + + +RX_SERVER_CURRENT_VERSION_RPM="$(basename build/reindexer-*server*.rpm)" +VERSION_FROM_RPM=$(echo "$RX_SERVER_CURRENT_VERSION_RPM" | grep -o '.*server-..') +VERSION=$(echo ${VERSION_FROM_RPM: -2:1}) # one-digit version + +echo "## choose latest release rpm file" +if [ $VERSION == 3 ]; then + LATEST_RELEASE=$(python3 cpp_src/cmd/reindexer_server/test/get_last_rx_version.py -v 3) + namespaces_list_expected=$'purchase_options_ext_dict\nchild_account_recommendations\n#config\n#activitystats\nradio_channels\ncollections\n#namespaces\nwp_imports_tasks\nepg_genres\nrecom_media_items_personal\nrecom_epg_archive_default\n#perfstats\nrecom_epg_live_default\nmedia_view_templates\nasset_video_servers\nwp_tasks_schedule\nadmin_roles\n#clientsstats\nrecom_epg_archive_personal\nrecom_media_items_similars\nmenu_items\naccount_recommendations\nkaraoke_items\nmedia_items\nbanners\n#queriesperfstats\nrecom_media_items_default\nrecom_epg_live_personal\nservices\n#memstats\nchannels\nmedia_item_recommendations\nwp_tasks_tasks\nepg' +elif [ $VERSION == 4 ]; then + LATEST_RELEASE=$(python3 cpp_src/cmd/reindexer_server/test/get_last_rx_version.py -v 4) + # replicationstats ns added for v4 + namespaces_list_expected=$'purchase_options_ext_dict\nchild_account_recommendations\n#config\n#activitystats\n#replicationstats\nradio_channels\ncollections\n#namespaces\nwp_imports_tasks\nepg_genres\nrecom_media_items_personal\nrecom_epg_archive_default\n#perfstats\nrecom_epg_live_default\nmedia_view_templates\nasset_video_servers\nwp_tasks_schedule\nadmin_roles\n#clientsstats\nrecom_epg_archive_personal\nrecom_media_items_similars\nmenu_items\naccount_recommendations\nkaraoke_items\nmedia_items\nbanners\n#queriesperfstats\nrecom_media_items_default\nrecom_epg_live_personal\nservices\n#memstats\nchannels\nmedia_item_recommendations\nwp_tasks_tasks\nepg' +else + echo "Unknown version" + exit 1 +fi + +echo "## downloading latest release rpm file: $LATEST_RELEASE" +curl "http://repo.itv.restr.im/itv-api-ng/7/x86_64/$LATEST_RELEASE" --output $LATEST_RELEASE; +echo "## downloading example DB" +curl "https://git.restream.ru/MaksimKravchuk/reindexer_testdata/-/raw/master/big.zip" --output big.zip; +unzip -o big.zip # unzips into mydb_big.rxdump; + +ADDRESS="cproto://127.0.0.1:6534/" +DB_NAME="test" + +memstats_expected=$'[ +{"replication":{"data_hash":24651210926,"data_count":3}}, +{"replication":{"data_hash":6252344969,"data_count":1}}, +{"replication":{"data_hash":37734732881,"data_count":28}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":1024095024522,"data_count":1145}}, +{"replication":{"data_hash":8373644068,"data_count":1315}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":7404222244,"data_count":97}}, +{"replication":{"data_hash":94132837196,"data_count":4}}, +{"replication":{"data_hash":1896088071,"data_count":2}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":-672103903,"data_count":33538}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":6833710705,"data_count":1}}, +{"replication":{"data_hash":5858155773472,"data_count":4500}}, +{"replication":{"data_hash":-473221280268823592,"data_count":65448}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":8288213744,"data_count":3}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":0,"data_count":0}}, +{"replication":{"data_hash":354171024786967,"data_count":3941}}, +{"replication":{"data_hash":-6520334670,"data_count":35886}}, +{"replication":{"data_hash":112772074632,"data_count":281}}, +{"replication":{"data_hash":-12679568198538,"data_count":1623116}} +] +Returned 27 rows' + +echo "##### Forward compatibility test #####" + +DB_PATH=$(pwd)"/rx_db" + +echo "Database: "$DB_PATH + +echo "## installing latest release: $LATEST_RELEASE" +yum install -y $LATEST_RELEASE > /dev/null; +# run RX server with disabled logging +reindexer_server -l warning --httplog=none --rpclog=none --db $DB_PATH & +server_pid=$! +sleep 2; + +reindexer_tool --dsn $ADDRESS$DB_NAME -f mydb_big.rxdump --createdb; +sleep 1; + +namespaces_1=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command '\namespaces list'); +echo $namespaces_1; +CompareNamespacesLists "${namespaces_1[@]}" "${namespaces_list_expected[@]}" $server_pid; + +memstats_1=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command 'select replication.data_hash, replication.data_count from #memstats'); +CompareMemstats "${memstats_1[@]}" "${memstats_expected[@]}" $server_pid; + +KillAndRemoveServer $server_pid; + +echo "## installing current version: $RX_SERVER_CURRENT_VERSION_RPM" +yum install -y build/*.rpm > /dev/null; +reindexer_server -l0 --corelog=none --httplog=none --rpclog=none --db $DB_PATH & +server_pid=$! +sleep 2; + +WaitForDB + +namespaces_2=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command '\namespaces list'); +echo $namespaces_2; +CompareNamespacesLists "${namespaces_2[@]}" "${namespaces_1[@]}" $server_pid; + +memstats_2=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command 'select replication.data_hash, replication.data_count from #memstats'); +CompareMemstats "${memstats_2[@]}" "${memstats_1[@]}" $server_pid; + +KillAndRemoveServer $server_pid; +rm -rf $DB_PATH; +sleep 1; + +echo "##### Backward compatibility test #####" + +echo "## installing current version: $RX_SERVER_CURRENT_VERSION_RPM" +yum install -y build/*.rpm > /dev/null; +reindexer_server -l warning --httplog=none --rpclog=none --db $DB_PATH & +server_pid=$! +sleep 2; + +reindexer_tool --dsn $ADDRESS$DB_NAME -f mydb_big.rxdump --createdb; +sleep 1; + +namespaces_3=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command '\namespaces list'); +echo $namespaces_3; +CompareNamespacesLists "${namespaces_3[@]}" "${namespaces_list_expected[@]}" $server_pid; + +memstats_3=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command 'select replication.data_hash, replication.data_count from #memstats'); +CompareMemstats "${memstats_3[@]}" "${memstats_expected[@]}" $server_pid; + +KillAndRemoveServer $server_pid; + +echo "## installing latest release: $LATEST_RELEASE" +yum install -y $LATEST_RELEASE > /dev/null; +reindexer_server -l warning --httplog=none --rpclog=none --db $DB_PATH & +server_pid=$! +sleep 2; + +WaitForDB + +namespaces_4=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command '\namespaces list'); +echo $namespaces_4; +CompareNamespacesLists "${namespaces_4[@]}" "${namespaces_3[@]}" $server_pid; + +memstats_4=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command 'select replication.data_hash, replication.data_count from #memstats'); +CompareMemstats "${memstats_4[@]}" "${memstats_3[@]}" $server_pid; + +KillAndRemoveServer $server_pid; +rm -rf $DB_PATH; diff --git a/cpp_src/cmd/reindexer_tool/commandsexecutor.cc b/cpp_src/cmd/reindexer_tool/commandsexecutor.cc index 77c3abb70..abb44ec41 100644 --- a/cpp_src/cmd/reindexer_tool/commandsexecutor.cc +++ b/cpp_src/cmd/reindexer_tool/commandsexecutor.cc @@ -6,6 +6,7 @@ #include "coroutine/waitgroup.h" #include "executorscommand.h" #include "tableviewscroller.h" +#include "tools/catch_and_return.h" #include "tools/fsops.h" #include "tools/jsontools.h" #include "tools/stringstools.h" @@ -191,7 +192,43 @@ Error CommandsExecutor::runImpl(const std::string& dsn, Args&&... a using reindexer::net::ev::sig; assertrx(!executorThr_.joinable()); - auto fn = [this](const std::string& dsn, Args&&... args) { + auto fnLoop = [this](const std::string& dsn, Args&&... args) { + std::string outputMode; + Error err; + if (reindexer::fs::ReadFile(reindexer::fs::JoinPath(reindexer::fs::GetHomeDir(), kConfigFile), outputMode) > 0) { + try { + gason::JsonParser jsonParser; + gason::JsonNode value = jsonParser.Parse(reindexer::giftStr(outputMode)); + for (auto node : value) { + WrSerializer ser; + reindexer::jsonValueToString(node.value, ser, 0, 0, false); + variables_[kVariableOutput] = std::string(ser.Slice()); + } + } catch (const gason::Exception& e) { + err = Error(errParseJson, "Unable to parse output mode: %s", e.what()); + } + } + if (err.ok() && variables_.empty()) { + variables_[kVariableOutput] = kOutputModeJson; + } + if (err.ok() && !uri_.parse(dsn)) { + err = Error(errNotValid, "Cannot connect to DB: Not a valid uri"); + } + if (err.ok()) err = db().Connect(dsn, std::forward(args)...); + if (err.ok()) { + loop_.spawn( + [this] { + // This coroutine should prevent loop from stopping for core::Reindexer + stopCh_.pop(); + }, + k8KStack); + } + std::lock_guard lck(mtx_); + status_.running = err.ok(); + status_.err = std::move(err); + }; + + auto fnThread = [this, &fnLoop](const std::string& dsn, Args&&... args) { sig sint; sint.set(loop_); sint.set([this](sig&) { cancelCtx_.Cancel(); }); @@ -214,49 +251,13 @@ Error CommandsExecutor::runImpl(const std::string& dsn, Args&&... a }); }); cmdAsync_.start(); - - auto fn = [this](const std::string& dsn, Args&&... args) { - std::string outputMode; - Error err; - if (reindexer::fs::ReadFile(reindexer::fs::JoinPath(reindexer::fs::GetHomeDir(), kConfigFile), outputMode) > 0) { - try { - gason::JsonParser jsonParser; - gason::JsonNode value = jsonParser.Parse(reindexer::giftStr(outputMode)); - for (auto node : value) { - WrSerializer ser; - reindexer::jsonValueToString(node.value, ser, 0, 0, false); - variables_[kVariableOutput] = std::string(ser.Slice()); - } - } catch (const gason::Exception& e) { - err = Error(errParseJson, "Unable to parse output mode: %s", e.what()); - } - } - if (err.ok() && variables_.empty()) { - variables_[kVariableOutput] = kOutputModeJson; - } - if (err.ok() && !uri_.parse(dsn)) { - err = Error(errNotValid, "Cannot connect to DB: Not a valid uri"); - } - if (err.ok()) err = db().Connect(dsn, std::forward(args)...); - if (err.ok()) { - loop_.spawn( - [this] { - // This coroutine should prevent loop from stopping for core::Reindexer - stopCh_.pop(); - }, - k8KStack); - } - std::lock_guard lck(mtx_); - status_.running = err.ok(); - status_.err = std::move(err); - }; - loop_.spawn(std::bind(fn, std::cref(dsn), std::forward(args)...)); + loop_.spawn(std::bind(fnLoop, std::cref(dsn), std::forward(args)...)); loop_.run(); }; setStatus(Status()); - executorThr_ = std::thread(std::bind(fn, std::cref(dsn), std::forward(args)...)); + executorThr_ = std::thread(std::bind(fnThread, std::cref(dsn), std::forward(args)...)); auto status = GetStatus(); while (!status.running && status.err.ok()) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); @@ -518,116 +519,114 @@ Error CommandsExecutor::getSuggestions(const std::string& input, st } template -Error CommandsExecutor::commandSelect(const std::string& command) { - typename DBInterface::QueryResultsT results(kResultsWithPayloadTypes | kResultsCJson | kResultsWithItemID | kResultsWithRaw); - Query q; +Error CommandsExecutor::commandSelect(const std::string& command) noexcept { try { - q.FromSQL(command); - } catch (const Error& err) { - return err; - } - - auto err = db().Select(q, results); - - if (err.ok()) { - if (results.Count()) { - auto& outputType = variables_[kVariableOutput]; - if (outputType == kOutputModeTable) { - auto isCanceled = [this]() -> bool { return cancelCtx_.IsCancelled(); }; - reindexer::TableViewBuilder tableResultsBuilder(results); - if (output_.IsCout() && !reindexer::isStdoutRedirected()) { - TableViewScroller resultsScroller(results, tableResultsBuilder, - reindexer::getTerminalSize().height - 1); - resultsScroller.Scroll(output_, isCanceled); + typename DBInterface::QueryResultsT results(kResultsWithPayloadTypes | kResultsCJson | kResultsWithItemID | kResultsWithRaw); + const auto q = Query::FromSQL(command); + + auto err = db().Select(q, results); + + if (err.ok()) { + if (results.Count()) { + auto& outputType = variables_[kVariableOutput]; + if (outputType == kOutputModeTable) { + auto isCanceled = [this]() -> bool { return cancelCtx_.IsCancelled(); }; + reindexer::TableViewBuilder tableResultsBuilder(results); + if (output_.IsCout() && !reindexer::isStdoutRedirected()) { + TableViewScroller resultsScroller(results, tableResultsBuilder, + reindexer::getTerminalSize().height - 1); + resultsScroller.Scroll(output_, isCanceled); + } else { + tableResultsBuilder.Build(output_(), isCanceled); + } } else { - tableResultsBuilder.Build(output_(), isCanceled); - } - } else { - if (!cancelCtx_.IsCancelled()) { - output_() << "[" << std::endl; - err = queryResultsToJson(output_(), results, q.IsWALQuery(), !output_.IsCout()); - output_() << "]" << std::endl; + if (!cancelCtx_.IsCancelled()) { + output_() << "[" << std::endl; + err = queryResultsToJson(output_(), results, q.IsWALQuery(), !output_.IsCout()); + output_() << "]" << std::endl; + } } } - } - const std::string& explain = results.GetExplainResults(); - if (!explain.empty() && !cancelCtx_.IsCancelled()) { - output_() << "Explain: " << std::endl; - if (variables_[kVariableOutput] == kOutputModePretty) { - WrSerializer ser; - prettyPrintJSON(reindexer::giftStr(explain), ser); - output_() << ser.Slice() << std::endl; - } else { - output_() << explain << std::endl; + const std::string& explain = results.GetExplainResults(); + if (!explain.empty() && !cancelCtx_.IsCancelled()) { + output_() << "Explain: " << std::endl; + if (variables_[kVariableOutput] == kOutputModePretty) { + WrSerializer ser; + prettyPrintJSON(reindexer::giftStr(explain), ser); + output_() << ser.Slice() << std::endl; + } else { + output_() << explain << std::endl; + } + } + if (!cancelCtx_.IsCancelled()) { + output_() << "Returned " << results.Count() << " rows"; + if (results.TotalCount()) output_() << ", total count " << results.TotalCount(); + output_() << std::endl; } - } - if (!cancelCtx_.IsCancelled()) { - output_() << "Returned " << results.Count() << " rows"; - if (results.TotalCount()) output_() << ", total count " << results.TotalCount(); - output_() << std::endl; - } - auto& aggResults = results.GetAggregationResults(); - if (aggResults.size() && !cancelCtx_.IsCancelled()) { - output_() << "Aggregations: " << std::endl; - for (auto& agg : aggResults) { - switch (agg.type) { - case AggFacet: { - assertrx(!agg.fields.empty()); - reindexer::h_vector maxW; - maxW.reserve(agg.fields.size()); - for (const auto& field : agg.fields) { - maxW.emplace_back(field.length()); - } - for (auto& row : agg.facets) { - assertrx(row.values.size() == agg.fields.size()); - for (size_t i = 0; i < row.values.size(); ++i) { - maxW.at(i) = std::max(maxW.at(i), int(row.values[i].length())); + auto& aggResults = results.GetAggregationResults(); + if (aggResults.size() && !cancelCtx_.IsCancelled()) { + output_() << "Aggregations: " << std::endl; + for (auto& agg : aggResults) { + switch (agg.type) { + case AggFacet: { + assertrx(!agg.fields.empty()); + reindexer::h_vector maxW; + maxW.reserve(agg.fields.size()); + for (const auto& field : agg.fields) { + maxW.emplace_back(field.length()); + } + for (auto& row : agg.facets) { + assertrx(row.values.size() == agg.fields.size()); + for (size_t i = 0; i < row.values.size(); ++i) { + maxW.at(i) = std::max(maxW.at(i), int(row.values[i].length())); + } } - } - int rowWidth = 8 + (maxW.size() - 1) * 2; - for (auto& mW : maxW) { - mW += 3; - rowWidth += mW; - } - for (size_t i = 0; i < agg.fields.size(); ++i) { - if (i != 0) output_() << "| "; - output_() << std::left << std::setw(maxW.at(i)) << agg.fields[i]; - } - output_() << "| count" << std::endl; - output_() << std::left << std::setw(rowWidth) << std::setfill('-') << "" << std::endl << std::setfill(' '); - for (auto& row : agg.facets) { - for (size_t i = 0; i < row.values.size(); ++i) { + int rowWidth = 8 + (maxW.size() - 1) * 2; + for (auto& mW : maxW) { + mW += 3; + rowWidth += mW; + } + for (size_t i = 0; i < agg.fields.size(); ++i) { if (i != 0) output_() << "| "; - output_() << std::left << std::setw(maxW.at(i)) << row.values[i]; + output_() << std::left << std::setw(maxW.at(i)) << agg.fields[i]; + } + output_() << "| count" << std::endl; + output_() << std::left << std::setw(rowWidth) << std::setfill('-') << "" << std::endl << std::setfill(' '); + for (auto& row : agg.facets) { + for (size_t i = 0; i < row.values.size(); ++i) { + if (i != 0) output_() << "| "; + output_() << std::left << std::setw(maxW.at(i)) << row.values[i]; + } + output_() << "| " << row.count << std::endl; + } + } break; + case AggDistinct: + assertrx(agg.fields.size() == 1); + output_() << "Distinct (" << agg.fields.front() << ")" << std::endl; + for (auto& v : agg.distincts) { + output_() << v.template As(agg.payloadType, agg.distinctsFields) << std::endl; } - output_() << "| " << row.count << std::endl; - } - } break; - case AggDistinct: - assertrx(agg.fields.size() == 1); - output_() << "Distinct (" << agg.fields.front() << ")" << std::endl; - for (auto& v : agg.distincts) { - output_() << v.template As(agg.payloadType, agg.distinctsFields) << std::endl; - } - output_() << "Returned " << agg.distincts.size() << " values" << std::endl; - break; - case AggSum: - case AggAvg: - case AggMin: - case AggMax: - case AggCount: - case AggCountCached: - case AggUnknown: - assertrx(agg.fields.size() == 1); - output_() << reindexer::AggTypeToStr(agg.type) << "(" << agg.fields.front() << ") = " << agg.GetValueOrZero() - << std::endl; + output_() << "Returned " << agg.distincts.size() << " values" << std::endl; + break; + case AggSum: + case AggAvg: + case AggMin: + case AggMax: + case AggCount: + case AggCountCached: + case AggUnknown: + assertrx(agg.fields.size() == 1); + output_() << reindexer::AggTypeToStr(agg.type) << "(" << agg.fields.front() << ") = " << agg.GetValueOrZero() + << std::endl; + } } } } + return err; } - return err; + CATCH_AND_RETURN; } template @@ -661,21 +660,19 @@ Error CommandsExecutor::commandUpsert(const std::string& command) { } template -Error CommandsExecutor::commandUpdateSQL(const std::string& command) { - typename DBInterface::QueryResultsT results; - Query q; +Error CommandsExecutor::commandUpdateSQL(const std::string& command) noexcept { try { - q.FromSQL(command); - } catch (const Error& err) { - return err; - } + typename DBInterface::QueryResultsT results; + Query q = Query::FromSQL(command); - auto err = db().Update(q, results); + auto err = db().Update(q, results); - if (err.ok()) { - output_() << "Updated " << results.Count() << " documents" << std::endl; + if (err.ok()) { + output_() << "Updated " << results.Count() << " documents" << std::endl; + } + return err; } - return err; + CATCH_AND_RETURN; } template @@ -695,20 +692,18 @@ Error CommandsExecutor::commandDelete(const std::string& command) { } template -Error CommandsExecutor::commandDeleteSQL(const std::string& command) { - typename DBInterface::QueryResultsT results; - Query q; +Error CommandsExecutor::commandDeleteSQL(const std::string& command) noexcept { try { - q.FromSQL(command); - } catch (const Error& err) { - return err; - } - auto err = db().Delete(q, results); + typename DBInterface::QueryResultsT results; + Query q = Query::FromSQL(command); + auto err = db().Delete(q, results); - if (err.ok()) { - output_() << "Deleted " << results.Count() << " documents" << std::endl; + if (err.ok()) { + output_() << "Deleted " << results.Count() << " documents" << std::endl; + } + return err; } - return err; + CATCH_AND_RETURN; } template diff --git a/cpp_src/cmd/reindexer_tool/commandsexecutor.h b/cpp_src/cmd/reindexer_tool/commandsexecutor.h index fbfe0db0a..0d4cc3835 100644 --- a/cpp_src/cmd/reindexer_tool/commandsexecutor.h +++ b/cpp_src/cmd/reindexer_tool/commandsexecutor.h @@ -80,11 +80,11 @@ class CommandsExecutor : public reindexer::IUpdatesObserver { Error processImpl(const std::string& command) noexcept; void stop(bool terminate); Error getSuggestions(const std::string& input, std::vector& suggestions); - Error commandSelect(const std::string& command); + Error commandSelect(const std::string& command) noexcept; Error commandUpsert(const std::string& command); - Error commandUpdateSQL(const std::string& command); + Error commandUpdateSQL(const std::string& command) noexcept; Error commandDelete(const std::string& command); - Error commandDeleteSQL(const std::string& command); + Error commandDeleteSQL(const std::string& command) noexcept; Error commandDump(const std::string& command); Error commandNamespaces(const std::string& command); Error commandMeta(const std::string& command); diff --git a/cpp_src/core/cbinding/reindexer_c.cc b/cpp_src/core/cbinding/reindexer_c.cc index 134937df5..d37229594 100644 --- a/cpp_src/core/cbinding/reindexer_c.cc +++ b/cpp_src/core/cbinding/reindexer_c.cc @@ -7,15 +7,11 @@ #include "cgocancelcontextpool.h" #include "core/cjson/baseencoder.h" -#include "core/selectfunc/selectfuncparser.h" -#include "core/transactionimpl.h" -#include "debug/allocdebug.h" #include "estl/syncpool.h" #include "reindexer_version.h" #include "resultserializer.h" #include "tools/logger.h" #include "tools/semversion.h" -#include "tools/stringstools.h" using namespace reindexer; const int kQueryResultsPoolSize = 1024; @@ -233,6 +229,9 @@ reindexer_ret reindexer_modify_item_packed(uintptr_t rx, reindexer_buffer args, case ModeDelete: err = rdxKeeper.db().Delete(ns, item, *res); break; + default: + err = Error(errParams, "Unexpected ItemModifyMode: %d", mode); + break; } } else { switch (mode) { @@ -248,6 +247,9 @@ reindexer_ret reindexer_modify_item_packed(uintptr_t rx, reindexer_buffer args, case ModeDelete: err = rdxKeeper.db().Delete(ns, item); break; + default: + err = Error(errParams, "Unexpected ItemModifyMode: %d", mode); + break; } if (err.ok()) { res->AddItem(item); @@ -496,17 +498,14 @@ reindexer_ret reindexer_select_query(uintptr_t rx, struct reindexer_buffer in, i Serializer ser(in.data, in.len); CGORdxCtxKeeper rdxKeeper(rx, ctx_info, ctx_pool); - Query q; - q.Deserialize(ser); + Query q = Query::Deserialize(ser); while (!ser.Eof()) { - JoinedQuery q1; - q1.joinType = JoinType(ser.GetVarUint()); - q1.Deserialize(ser); - q1.debugLevel = q.debugLevel; + const auto joinType = JoinType(ser.GetVarUint()); + JoinedQuery q1{joinType, Query::Deserialize(ser)}; if (q1.joinType == JoinType::Merge) { - q.mergeQueries_.emplace_back(std::move(q1)); + q.Merge(std::move(q1)); } else { - q.joinQueries_.emplace_back(std::move(q1)); + q.AddJoinQuery(std::move(q1)); } } @@ -515,7 +514,7 @@ reindexer_ret reindexer_select_query(uintptr_t rx, struct reindexer_buffer in, i return ret2c(err_too_many_queries, out); } err = rdxKeeper.db().Select(q, *result); - if (q.debugLevel >= LogError && err.code() != errOK) logPrintf(LogError, "Query error %s", err.what()); + if (q.GetDebugLevel() >= LogError && err.code() != errOK) logPrintf(LogError, "Query error %s", err.what()); if (err.ok()) { results2c(std::move(result), &out, as_json, pt_versions, pt_versions_count); } else { @@ -540,16 +539,15 @@ reindexer_ret reindexer_delete_query(uintptr_t rx, reindexer_buffer in, reindexe Serializer ser(in.data, in.len); CGORdxCtxKeeper rdxKeeper(rx, ctx_info, ctx_pool); - Query q; + Query q = Query::Deserialize(ser); q.type_ = QueryDelete; - q.Deserialize(ser); auto result{new_results()}; if (!result) { return ret2c(err_too_many_queries, out); } res = rdxKeeper.db().Delete(q, *result); - if (q.debugLevel >= LogError && res.code() != errOK) logPrintf(LogError, "Query error %s", res.what()); + if (q.GetDebugLevel() >= LogError && res.code() != errOK) logPrintf(LogError, "Query error %s", res.what()); if (res.ok()) { results2c(std::move(result), &out); } @@ -569,15 +567,14 @@ reindexer_ret reindexer_update_query(uintptr_t rx, reindexer_buffer in, reindexe Serializer ser(in.data, in.len); CGORdxCtxKeeper rdxKeeper(rx, ctx_info, ctx_pool); - Query q; - q.Deserialize(ser); + Query q = Query::Deserialize(ser); q.type_ = QueryUpdate; auto result{new_results()}; if (!result) { return ret2c(err_too_many_queries, out); } res = rdxKeeper.db().Update(q, *result); - if (q.debugLevel >= LogError && res.code() != errOK) logPrintf(LogError, "Query error %s", res.what()); + if (q.GetDebugLevel() >= LogError && res.code() != errOK) logPrintf(LogError, "Query error %s", res.what()); if (res.ok()) { int32_t ptVers = -1; results2c(std::move(result), &out, 0, &ptVers, 1); @@ -599,9 +596,8 @@ reindexer_error reindexer_delete_query_tx(uintptr_t rx, uintptr_t tr, reindexer_ return error2c(errOK); } Serializer ser(in.data, in.len); - Query q; try { - q.Deserialize(ser); + Query q = Query::Deserialize(ser); q.type_ = QueryDelete; trw->tr_.Modify(std::move(q)); @@ -622,9 +618,8 @@ reindexer_error reindexer_update_query_tx(uintptr_t rx, uintptr_t tr, reindexer_ return error2c(errOK); } Serializer ser(in.data, in.len); - Query q; try { - q.Deserialize(ser); + Query q = Query::Deserialize(ser); q.type_ = QueryUpdate; trw->tr_.Modify(std::move(q)); diff --git a/cpp_src/core/cjson/jsonbuilder.cc b/cpp_src/core/cjson/jsonbuilder.cc index bb8905d7a..2c57fcb51 100644 --- a/cpp_src/core/cjson/jsonbuilder.cc +++ b/cpp_src/core/cjson/jsonbuilder.cc @@ -3,7 +3,8 @@ namespace reindexer { -JsonBuilder::JsonBuilder(WrSerializer &ser, ObjType type, const TagsMatcher *tm) : ser_(&ser), tm_(tm), type_(type) { +JsonBuilder::JsonBuilder(WrSerializer &ser, ObjType type, const TagsMatcher *tm, bool emitTrailingForFloat) + : ser_(&ser), tm_(tm), type_(type), emitTrailingForFloat_(emitTrailingForFloat) { switch (type_) { case ObjType::TypeArray: (*ser_) << '['; @@ -38,12 +39,12 @@ JsonBuilder &JsonBuilder::End() { JsonBuilder JsonBuilder::Object(std::string_view name, int /*size*/) { putName(name); - return JsonBuilder(*ser_, ObjType::TypeObject, tm_); + return JsonBuilder(*ser_, ObjType::TypeObject, tm_, emitTrailingForFloat_); } JsonBuilder JsonBuilder::Array(std::string_view name, int /*size*/) { putName(name); - return JsonBuilder(*ser_, ObjType::TypeArray, tm_); + return JsonBuilder(*ser_, ObjType::TypeArray, tm_, emitTrailingForFloat_); } void JsonBuilder::putName(std::string_view name) { diff --git a/cpp_src/core/cjson/jsonbuilder.h b/cpp_src/core/cjson/jsonbuilder.h index ccdc04b07..b46555ebe 100644 --- a/cpp_src/core/cjson/jsonbuilder.h +++ b/cpp_src/core/cjson/jsonbuilder.h @@ -10,16 +10,18 @@ namespace reindexer { class JsonBuilder { public: JsonBuilder() noexcept : ser_(nullptr), tm_(nullptr) {} - JsonBuilder(WrSerializer &ser, ObjType type = ObjType::TypeObject, const TagsMatcher *tm = nullptr); + JsonBuilder(WrSerializer &ser, ObjType type = ObjType::TypeObject, const TagsMatcher *tm = nullptr, bool emitTrailingForFloat = true); ~JsonBuilder() { End(); } JsonBuilder(const JsonBuilder &) = delete; - JsonBuilder(JsonBuilder &&other) : ser_(other.ser_), tm_(other.tm_), type_(other.type_), count_(other.count_) { + JsonBuilder(JsonBuilder &&other) noexcept + : ser_(other.ser_), tm_(other.tm_), type_(other.type_), count_(other.count_), emitTrailingForFloat_(other.emitTrailingForFloat_) { other.type_ = ObjType::TypePlain; } JsonBuilder &operator=(const JsonBuilder &) = delete; JsonBuilder &operator=(JsonBuilder &&) = delete; void SetTagsMatcher(const TagsMatcher *tm) noexcept { tm_ = tm; } + void EmitTrailingForFloat(bool val) noexcept { emitTrailingForFloat_ = val; } /// Start new object JsonBuilder Object(std::string_view name = {}, int size = KUnknownFieldSize); @@ -56,12 +58,22 @@ class JsonBuilder { JsonBuilder &Put(std::string_view name, Uuid arg, int offset = 0); JsonBuilder &Put(std::nullptr_t, std::string_view arg, int offset = 0) { return Put(std::string_view{}, arg, offset); } JsonBuilder &Put(std::string_view name, const char *arg, int offset = 0) { return Put(name, std::string_view(arg), offset); } - template ::value || std::is_floating_point::value>::type * = nullptr> + template ::value>::type * = nullptr> JsonBuilder &Put(std::string_view name, const T &arg, int /*offset*/ = 0) { putName(name); (*ser_) << arg; return *this; } + template ::value>::type * = nullptr> + JsonBuilder &Put(std::string_view name, const T &arg, int /*offset*/ = 0) { + putName(name); + if (emitTrailingForFloat_) { + (*ser_) << arg; + } else { + ser_->PutDoubleStrNoTrailing(arg); + } + return *this; + } template JsonBuilder &Put(int tagName, const T &arg, int offset = 0) { return Put(getNameByTag(tagName), arg, offset); @@ -86,6 +98,7 @@ class JsonBuilder { const TagsMatcher *tm_; ObjType type_ = ObjType::TypePlain; int count_ = 0; + bool emitTrailingForFloat_ = true; }; } // namespace reindexer diff --git a/cpp_src/core/cjson/tagsmatcherimpl.h b/cpp_src/core/cjson/tagsmatcherimpl.h index 80577249c..c310ade55 100644 --- a/cpp_src/core/cjson/tagsmatcherimpl.h +++ b/cpp_src/core/cjson/tagsmatcherimpl.h @@ -186,7 +186,6 @@ class TagsMatcherImpl { names2tags_.emplace(name, tag); tags2names_[tag] = name; } - version_++; // assert(ser.Eof()); } void deserialize(Serializer &ser, int version, int stateToken) { diff --git a/cpp_src/core/dbconfig.cc b/cpp_src/core/dbconfig.cc index 60ebb6550..0a7635463 100644 --- a/cpp_src/core/dbconfig.cc +++ b/cpp_src/core/dbconfig.cc @@ -267,10 +267,10 @@ void ReplicationConfigData::GetYAML(WrSerializer &ser) const { "# Force resync on wrong data hash conditions\n" "force_sync_on_wrong_data_hash: " + (forceSyncOnWrongDataHash ? "true" : "false") + "\n" "\n" - "# Resync timeout on network errors" + "# Resync timeout on network errors\n" "retry_sync_interval_sec: " + std::to_string(retrySyncIntervalSec) + "\n" "\n" - "# Count of online replication erros, which will be merged in single error message" + "# Count of online replication erros, which will be merged in single error message\n" "online_repl_errors_threshold: " + std::to_string(onlineReplErrorsThreshold) + "\n" "\n" "# List of namespaces for replication. If emply, all namespaces\n" diff --git a/cpp_src/core/defnsconfigs.h b/cpp_src/core/defnsconfigs.h index 04fec8aa3..1601c2b68 100644 --- a/cpp_src/core/defnsconfigs.h +++ b/cpp_src/core/defnsconfigs.h @@ -75,6 +75,7 @@ const std::vector kDefDBConfig = { "replication":{ "role":"none", "master_dsn":"cproto://127.0.0.1:6534/db", + "server_id":0, "cluster_id":2, "force_sync_on_logic_error": false, "force_sync_on_wrong_data_hash": false, diff --git a/cpp_src/core/expressiontree.h b/cpp_src/core/expressiontree.h index 0eeaced61..98b3521e2 100644 --- a/cpp_src/core/expressiontree.h +++ b/cpp_src/core/expressiontree.h @@ -18,7 +18,7 @@ class Bracket { void Append() noexcept { ++size_; } /// Decrease space occupied by children void Erase(size_t length) noexcept { - assertrx(size_ > length); + assertrx_throw(size_ > length); size_ -= length; } void CopyPayloadFrom(const Bracket&) const noexcept {} @@ -37,18 +37,6 @@ struct Skip {}; /// For detailed documentation see expressiontree.md template class ExpressionTree { - template - class Ref { - public: - explicit Ref(T& v) noexcept : ptr_{&v} {} - operator T&() noexcept { return *ptr_; } - operator const T&() const noexcept { return *ptr_; } - bool operator==(const Ref& other) const noexcept(noexcept(std::declval() == std::declval())) { return *ptr_ == *other.ptr_; } - - private: - T* ptr_; - }; - template struct OverloadResolutionHelper : private OverloadResolutionHelper { constexpr static T resolve(std::function) noexcept; @@ -77,11 +65,6 @@ class ExpressionTree { R operator()(Arg&& arg) const noexcept(noexcept(std::declval()(std::forward(arg)))) { return functor_(std::forward(arg)); } - R operator()(const Ref& arg) const noexcept(noexcept(std::declval()(arg))) { return functor_(arg); } - R operator()(Ref& arg) const noexcept(noexcept(std::declval()(arg))) { return functor_(arg); } - R operator()(Ref&& arg) const noexcept(noexcept(std::declval()(std::forward>(arg)))) { - return functor_(std::forward>(arg)); - } private: F functor_; @@ -102,18 +85,6 @@ class ExpressionTree { R operator()(Arg&& arg) const noexcept(noexcept(std::declval()(std::forward(arg)))) { return functor_(std::forward(arg)); } - template - R operator()(const Ref& arg) const noexcept(noexcept(std::declval()(arg))) { - return functor_(arg); - } - template - R operator()(Ref& arg) const noexcept(noexcept(std::declval()(arg))) { - return functor_(arg); - } - template - R operator()(Ref&& arg) const noexcept(noexcept(std::declval()(std::forward>(arg)))) { - return functor_(std::forward>(arg)); - } private: F functor_; @@ -142,9 +113,6 @@ class ExpressionTree { void operator()(const T&) const noexcept {} void operator()(T&) const noexcept {} void operator()(T&&) const noexcept {} - void operator()(const Ref&) const noexcept {} - void operator()(Ref&) const noexcept {} - void operator()(Ref&&) const noexcept {} }; template class SkipHelper { @@ -152,9 +120,6 @@ class ExpressionTree { void operator()(const T&) const noexcept {} void operator()(T&) const noexcept {} void operator()(T&&) const noexcept {} - void operator()(const Ref&) const noexcept {} - void operator()(Ref&) const noexcept {} - void operator()(Ref&&) const noexcept {} }; template class VisitorHelper, Fs...> : private SkipHelper, private VisitorHelper { @@ -190,7 +155,7 @@ class ExpressionTree { class Node { friend ExpressionTree; - using Storage = std::variant...>; + using Storage = std::variant; struct SizeVisitor { template @@ -203,20 +168,18 @@ class ExpressionTree { template struct GetVisitor { T& operator()(T& v) const noexcept { return v; } - T& operator()(Ref& r) const noexcept { return r; } template T& operator()(U&) const noexcept { - assertrx(0); + assertrx_throw(0); abort(); } }; template struct GetVisitor { const T& operator()(const T& v) const noexcept { return v; } - const T& operator()(const Ref& r) const noexcept { return r; } template const T& operator()(const U&) const noexcept { - assertrx(0); + assertrx_throw(0); abort(); } }; @@ -225,62 +188,25 @@ class ExpressionTree { bool operator()(const T& lhs, const T& rhs) const noexcept(noexcept(lhs == rhs)) { return lhs == rhs; } - template - bool operator()(const Ref& lhs, const T& rhs) const noexcept(noexcept(rhs == rhs)) { - return static_cast(lhs) == rhs; - } - template - bool operator()(const T& lhs, const Ref& rhs) const noexcept(noexcept(lhs == lhs)) { - return lhs == static_cast(rhs); - } template bool operator()(const T&, const U&) const noexcept { return false; } }; - struct LazyCopyVisitor { - Storage operator()(SubTree& st) const noexcept { return st; } - template - Storage operator()(Ref& r) const { - return r; - } - template - Storage operator()(T& v) const { - return Ref{v}; - } - }; - struct DeepCopyVisitor { + struct CopyVisitor { Storage operator()(const SubTree& st) const noexcept { return st; } template - Storage operator()(const Ref& r) const { - return static_cast(r); - } - template Storage operator()(const T& v) const { return v; } }; - struct DeepRValueCopyVisitor { + struct MoveVisitor { Storage operator()(SubTree&& st) const noexcept { return std::move(st); } template - Storage operator()(Ref&& r) const { - return static_cast(r); - } - template Storage operator()(T&& v) const { return std::forward(v); } }; - struct IsRefVisitor { - template - bool operator()(const T&) const noexcept { - return false; - } - template - bool operator()(const Ref&) const noexcept { - return true; - } - }; public: Node() : storage_{std::in_place_type, 1} {} @@ -325,13 +251,9 @@ class ExpressionTree { bool IsSubTree() const noexcept { return storage_.index() == 0; } bool IsLeaf() const noexcept { return !IsSubTree(); } template - bool Holds() const noexcept { + bool Is() const noexcept { return std::holds_alternative(storage_); } - template - bool HoldsOrReferTo() const noexcept { - return std::holds_alternative(storage_) || std::holds_alternative>(storage_); - } void Append() { std::get(storage_).Append(); } void Erase(size_t length) { std::get(storage_).Erase(length); } /// Execute appropriate functor depending on content type @@ -344,22 +266,14 @@ class ExpressionTree { return std::visit(Visitor{std::forward(funcs)...}, storage_); } - Node MakeLazyCopy() & { - static const LazyCopyVisitor visitor; - return {operation, std::visit(visitor, storage_)}; - } - Node MakeDeepCopy() const& { - static const DeepCopyVisitor visitor; + Node Copy() const& { + static const CopyVisitor visitor; return {operation, std::visit(visitor, storage_)}; } - Node MakeDeepCopy() && { - static const DeepRValueCopyVisitor visitor; + Node Move() && { + static const MoveVisitor visitor; return {operation, std::visit(visitor, std::move(storage_))}; } - bool IsRef() const { - static const IsRefVisitor visitor; - return std::visit(visitor, storage_); - } template void SetValue(T&& v) { storage_ = std::forward(v); @@ -385,13 +299,13 @@ class ExpressionTree { ExpressionTree& operator=(ExpressionTree&&) = default; ExpressionTree(const ExpressionTree& other) : activeBrackets_{other.activeBrackets_} { container_.reserve(other.container_.size()); - for (const Node& n : other.container_) container_.emplace_back(n.MakeDeepCopy()); + for (const Node& n : other.container_) container_.emplace_back(n.Copy()); } ExpressionTree& operator=(const ExpressionTree& other) { if (this == &other) return *this; container_.clear(); container_.reserve(other.container_.size()); - for (const Node& n : other.container_) container_.emplace_back(n.MakeDeepCopy()); + for (const Node& n : other.container_) container_.emplace_back(n.Copy()); activeBrackets_ = other.activeBrackets_; return *this; } @@ -407,9 +321,9 @@ class ExpressionTree { /// Insert value at the position template void Insert(size_t pos, OperationType op, T&& v) { - assertrx(pos < container_.size()); + assertrx_throw(pos < container_.size()); for (unsigned& b : activeBrackets_) { - assertrx(b < container_.size()); + assertrx_throw(b < container_.size()); if (b >= pos) ++b; } for (size_t i = 0; i < pos; ++i) { @@ -420,9 +334,9 @@ class ExpressionTree { /// Insert value after the position template void InsertAfter(size_t pos, OperationType op, T&& v) { - assertrx(pos < container_.size()); + assertrx_throw(pos < container_.size()); for (unsigned& b : activeBrackets_) { - assertrx(b < container_.size()); + assertrx_throw(b < container_.size()); if (b > pos) ++b; } for (size_t i = 0; i < pos; ++i) { @@ -434,7 +348,7 @@ class ExpressionTree { template void Append(OperationType op, T&& v) { for (unsigned i : activeBrackets_) { - assertrx(i < container_.size()); + assertrx_throw(i < container_.size()); container_[i].Append(); } container_.emplace_back(op, std::forward(v)); @@ -443,7 +357,7 @@ class ExpressionTree { template void Append(OperationType op, const T& v) { for (unsigned i : activeBrackets_) { - assertrx(i < container_.size()); + assertrx_throw(i < container_.size()); container_[i].Append(); } container_.emplace_back(op, v); @@ -452,7 +366,7 @@ class ExpressionTree { template void Append(OperationType op, Args&&... args) { for (unsigned i : activeBrackets_) { - assertrx(i < container_.size()); + assertrx_throw(i < container_.size()); container_[i].Append(); } container_.emplace_back(op, T{std::forward(args)...}); @@ -463,11 +377,6 @@ class ExpressionTree { container_.reserve(container_.size() + (end.PlainIterator() - begin.PlainIterator())); append(begin, end); } - class iterator; - void LazyAppend(iterator begin, iterator end) { - container_.reserve(container_.size() + (end.PlainIterator() - begin.PlainIterator())); - lazyAppend(begin, end); - } /// Appends value as first child of the root template @@ -475,13 +384,24 @@ class ExpressionTree { for (unsigned& i : activeBrackets_) ++i; container_.emplace(container_.begin(), op, std::forward(v)); } + void PopBack() { + assertrx_throw(!container_.empty()); + for (unsigned i : activeBrackets_) { + assertrx_throw(i < container_.size()); + container_[i].Erase(1); + } + if (container_.back().IsSubTree() && !activeBrackets_.empty() && activeBrackets_.back() == container_.size() - 1) { + activeBrackets_.pop_back(); + } + container_.pop_back(); + } /// Enclose area in brackets template void EncloseInBracket(size_t from, size_t to, OperationType op, Args&&... args) { - assertrx(to > from); - assertrx(to <= container_.size()); + assertrx_throw(to > from); + assertrx_throw(to <= container_.size()); for (unsigned& b : activeBrackets_) { - assertrx(b < container_.size()); + assertrx_throw(b < container_.size()); if (b >= from) ++b; } for (size_t i = 0; i < from; ++i) { @@ -490,14 +410,14 @@ class ExpressionTree { if (bracketEnd >= to) { container_[i].Append(); } else { - assertrx(bracketEnd <= from); + assertrx_throw(bracketEnd <= from); } } } #ifndef NDEBUG for (size_t i = from; i < to; ++i) { if (container_[i].IsSubTree()) { - assertrx(Next(i) <= to); + assertrx_throw(Next(i) <= to); } } #endif @@ -507,7 +427,7 @@ class ExpressionTree { template void OpenBracket(OperationType op, Args&&... args) { for (unsigned i : activeBrackets_) { - assertrx(i < container_.size()); + assertrx_throw(i < container_.size()); container_[i].Append(); } activeBrackets_.push_back(container_.size()); @@ -525,55 +445,55 @@ class ExpressionTree { void Reserve(size_t s) { container_.reserve(s); } /// @return size of leaf of subtree beginning from i size_t Size(size_t i) const noexcept { - assertrx(i < Size()); + assertrx_throw(i < Size()); return container_[i].Size(); } /// @return beginning of next children of the same parent size_t Next(size_t i) const noexcept { - assertrx(i < Size()); + assertrx_throw(i < Size()); return i + Size(i); } template - bool HoldsOrReferTo(size_t i) const noexcept { - assertrx(i < Size()); - return container_[i].template HoldsOrReferTo(); + bool Is(size_t i) const noexcept { + assertrx_throw(i < Size()); + return container_[i].template Is(); } bool IsSubTree(size_t i) const noexcept { - assertrx(i < Size()); + assertrx_throw(i < Size()); return container_[i].IsSubTree(); } OperationType GetOperation(size_t i) const noexcept { - assertrx(i < Size()); + assertrx_throw(i < Size()); return container_[i].operation; } void SetOperation(OperationType op, size_t i) noexcept { - assertrx(i < Size()); + assertrx_throw(i < Size()); container_[i].operation = op; } template T& Get(size_t i) { - assertrx(i < Size()); + assertrx_throw(i < Size()); return container_[i].template Value(); } template const T& Get(size_t i) const { - assertrx(i < Size()); + assertrx_throw(i < Size()); return container_[i].template Value(); } template void SetValue(size_t i, T&& v) { - assertrx(i < Size()); + assertrx_throw(i < Size()); return container_[i].template SetValue(std::forward(v)); } void Erase(size_t from, size_t to) { - assertrx(to >= from); + assertrx_throw(to >= from); const size_t count = to - from; for (size_t i = 0; i < from; ++i) { if (container_[i].IsSubTree()) { if (Next(i) >= to) { container_[i].Erase(count); } else { - assertrx(Next(i) <= from); + assertrx_throw(Next(i) <= from); } } } @@ -588,12 +508,12 @@ class ExpressionTree { /// Execute appropriate functor depending on content type template R InvokeAppropriate(size_t i, Fs&&... funcs) { - assertrx(i < container_.size()); + assertrx_throw(i < container_.size()); return container_[i].template InvokeAppropriate(std::forward(funcs)...); } template R InvokeAppropriate(size_t i, Fs&&... funcs) const { - assertrx(i < container_.size()); + assertrx_throw(i < container_.size()); return container_[i].template InvokeAppropriate(std::forward(funcs)...); } /// Execute appropriate functor depending on content type for each node, skip if no appropriate functor @@ -623,12 +543,12 @@ class ExpressionTree { return *this; } const_iterator cbegin() const noexcept { - assertrx(it_->IsSubTree()); + assertrx_throw(it_->IsSubTree()); return it_ + 1; } const_iterator begin() const noexcept { return cbegin(); } const_iterator cend() const noexcept { - assertrx(it_->IsSubTree()); + assertrx_throw(it_->IsSubTree()); return it_ + it_->Size(); } const_iterator end() const noexcept { return cend(); } @@ -653,12 +573,12 @@ class ExpressionTree { } operator const_iterator() const noexcept { return const_iterator(it_); } iterator begin() const noexcept { - assertrx(it_->IsSubTree()); + assertrx_throw(it_->IsSubTree()); return it_ + 1; } const_iterator cbegin() const noexcept { return begin(); } iterator end() const noexcept { - assertrx(it_->IsSubTree()); + assertrx_throw(it_->IsSubTree()); return it_ + it_->Size(); } const_iterator cend() const noexcept { return end(); } @@ -706,7 +626,7 @@ class ExpressionTree { /// @return the last appended leaf or last closed subtree or last openned subtree if it is empty size_t lastAppendedElement() const noexcept { - assertrx(!container_.empty()); + assertrx_throw(!container_.empty()); size_t start = 0; // start of last openned subtree; if (!activeBrackets_.empty()) { start = activeBrackets_.back() + 1; @@ -729,28 +649,6 @@ class ExpressionTree { [this, op](const auto& v) -> void { this->Append(op, v); }); } } - - void lazyAppend(iterator begin, iterator end) { - for (; begin != end; ++begin) { - const OpType op = begin->operation; - begin->template InvokeAppropriate( - [this, &begin, op](const SubTree& b) { - OpenBracket(op); - std::get(container_.back().storage_).CopyPayloadFrom(b); - lazyAppend(begin.begin(), begin.end()); - CloseBracket(); - }, - [this, op](auto& v) -> void { this->Append(op, Ref>{v}); }); - } - } - - ExpressionTree makeLazyCopy() & { - ExpressionTree result; - result.container_.reserve(container_.size()); - for (Node& n : container_) result.container_.emplace_back(n.MakeLazyCopy()); - result.activeBrackets_ = activeBrackets_; - return result; - } }; } // namespace reindexer diff --git a/cpp_src/core/ft/areaholder.h b/cpp_src/core/ft/areaholder.h index e4db54a9f..fb186f6b0 100644 --- a/cpp_src/core/ft/areaholder.h +++ b/cpp_src/core/ft/areaholder.h @@ -39,7 +39,8 @@ class AreaBuffer { [[nodiscard]] bool Empty() const noexcept { return data_.empty(); } void Commit() { if (!data_.empty()) { - boost::sort::pdqsort(data_.begin(), data_.end(), [](const Area &rhs, const Area &lhs) { return rhs.start < lhs.start; }); + boost::sort::pdqsort_branchless(data_.begin(), data_.end(), + [](const Area &rhs, const Area &lhs) noexcept { return rhs.start < lhs.start; }); for (auto vit = data_.begin() + 1; vit != data_.end(); ++vit) { auto prev = vit - 1; if (vit->Concat(*prev)) { diff --git a/cpp_src/core/ft/ft_fast/dataprocessor.cc b/cpp_src/core/ft/ft_fast/dataprocessor.cc index 772b1c785..1b3df8eb0 100644 --- a/cpp_src/core/ft/ft_fast/dataprocessor.cc +++ b/cpp_src/core/ft/ft_fast/dataprocessor.cc @@ -149,13 +149,16 @@ size_t DataProcessor::buildWordsMap(words_map &words_um) { auto &vdocs = holder_.vdocs_; const int fieldscount = fieldSize_; size_t offset = holder_.vdocsOffset_; + auto cycleSize = vdocsTexts.size() / maxIndexWorkers + (vdocsTexts.size() % maxIndexWorkers ? 1 : 0); // build words map parallel in maxIndexWorkers threads - auto worker = [this, &ctxs, &vdocsTexts, offset, maxIndexWorkers, fieldscount, &cfg, &vdocs](int i) { + auto worker = [this, &ctxs, &vdocsTexts, offset, cycleSize, fieldscount, &cfg, &vdocs](int i) { auto ctx = &ctxs[i]; std::string word, str; std::vector wrds; std::vector virtualWords; - for (VDocIdType j = i, sz = VDocIdType(vdocsTexts.size()); j < sz; j += maxIndexWorkers) { + size_t start = cycleSize * i; + size_t fin = std::min(cycleSize * (i + 1), vdocsTexts.size()); + for (VDocIdType j = start; j < fin; ++j) { const size_t vdocId = offset + j; auto &vdoc = vdocs[vdocId]; vdoc.wordsCount.insert(vdoc.wordsCount.begin(), fieldscount, 0.0); diff --git a/cpp_src/core/ft/ft_fast/selecter.cc b/cpp_src/core/ft/ft_fast/selecter.cc index b460ca929..40082ae17 100644 --- a/cpp_src/core/ft/ft_fast/selecter.cc +++ b/cpp_src/core/ft/ft_fast/selecter.cc @@ -335,8 +335,8 @@ void Selecter::processLowRelVariants(FtSelectContext& ctx, const FtMerge return false; }); } else { - boost::sort::pdqsort(ctx.lowRelVariants.begin(), ctx.lowRelVariants.end(), - [](FtBoundVariantEntry& l, FtBoundVariantEntry& r) noexcept { return l.proc > r.proc; }); + boost::sort::pdqsort_branchless(ctx.lowRelVariants.begin(), ctx.lowRelVariants.end(), + [](FtBoundVariantEntry& l, FtBoundVariantEntry& r) noexcept { return l.proc > r.proc; }); } auto lastVariantLen = ctx.lowRelVariants.size() ? ctx.lowRelVariants[0].GetLenCached() : -1; @@ -790,7 +790,7 @@ std::pair Selecter::calcTermRank(const TextSearchResults& r if (!termRank) return std::make_pair(termRank, field); if (holder_.cfg_->summationRanksByFieldsRatio > 0) { - std::sort(ranksInFields.begin(), ranksInFields.end()); + boost::sort::pdqsort_branchless(ranksInFields.begin(), ranksInFields.end()); double k = holder_.cfg_->summationRanksByFieldsRatio; for (auto rank : ranksInFields) { termRank += (k * rank); @@ -921,9 +921,10 @@ void Selecter::mergeIterationGroup(TextSearchResults& rawRes, index_t ra mergedPosInfo.rank = 0; } else { auto& posTmp = mergedPosInfo.posTmp; - boost::sort::pdqsort( - posTmp.begin(), posTmp.end(), - [](const std::pair& l, const std::pair& r) { return l.first < r.first; }); + boost::sort::pdqsort_branchless(posTmp.begin(), posTmp.end(), + [](const std::pair& l, + const std::pair& r) noexcept { return l.first < r.first; }); + auto last = std::unique(posTmp.begin(), posTmp.end()); posTmp.resize(last - posTmp.begin()); @@ -984,9 +985,9 @@ void Selecter::mergeResultsPart(std::vector& rawResul merged.maxRank = m.proc; } } - - boost::sort::pdqsort(merged.begin(), merged.end(), - [](const IDataHolder::MergeInfo& lhs, const IDataHolder::MergeInfo& rhs) { return lhs.proc > rhs.proc; }); + boost::sort::pdqsort_branchless( + merged.begin(), merged.end(), + [](const IDataHolder::MergeInfo& lhs, const IDataHolder::MergeInfo& rhs) noexcept { return lhs.proc > rhs.proc; }); } template @@ -1244,12 +1245,11 @@ typename IDataHolder::MergeData Selecter::mergeResults(std::vector merged_rd; std::vector idoffsets; - for (auto& rawRes : rawResults) { - boost::sort::pdqsort(rawRes.begin(), rawRes.end(), - [](const TextSearchResult& lhs, const TextSearchResult& rhs) { return lhs.proc_ > rhs.proc_; }); + boost::sort::pdqsort_branchless( + rawRes.begin(), rawRes.end(), + [](const TextSearchResult& lhs, const TextSearchResult& rhs) noexcept { return lhs.proc_ > rhs.proc_; }); } - const auto maxMergedSize = std::min(size_t(holder_.cfg_->mergeLimit), totalORVids); merged.reserve(maxMergedSize); @@ -1332,8 +1332,9 @@ typename IDataHolder::MergeData Selecter::mergeResults(std::vector rhs.proc; }); + boost::sort::pdqsort_branchless( + merged.begin(), merged.end(), + [](const IDataHolder::MergeInfo& lhs, const IDataHolder::MergeInfo& rhs) noexcept { return lhs.proc > rhs.proc; }); return merged; } diff --git a/cpp_src/core/ft/ft_fuzzy/merger/basemerger.cc b/cpp_src/core/ft/ft_fuzzy/merger/basemerger.cc index 967161001..12a57498c 100644 --- a/cpp_src/core/ft/ft_fuzzy/merger/basemerger.cc +++ b/cpp_src/core/ft/ft_fuzzy/merger/basemerger.cc @@ -93,7 +93,7 @@ SearchResult BaseMerger::Merge(MergeCtx& ctx, bool inTransaction, const reindexe data_set.AddData(it->Id(), id_ctx); } } - boost::sort::pdqsort(data_set.data_->begin(), data_set.data_->end(), [](const MergedData& lhs, const MergedData& rhs) { + boost::sort::pdqsort(data_set.data_->begin(), data_set.data_->end(), [](const MergedData& lhs, const MergedData& rhs) noexcept { if (lhs.proc_ == rhs.proc_) { return lhs.id_ < rhs.id_; } diff --git a/cpp_src/core/ft/idrelset.cc b/cpp_src/core/ft/idrelset.cc index 7f31546d1..6b87bc15c 100644 --- a/cpp_src/core/ft/idrelset.cc +++ b/cpp_src/core/ft/idrelset.cc @@ -1,4 +1,3 @@ - #include "idrelset.h" #include #include "estl/h_vector.h" @@ -84,9 +83,4 @@ int IdRelSet::Add(VDocIdType id, int pos, int field) { return back().Size(); } -void IdRelType::SimpleCommit() { - boost::sort::pdqsort(pos_.begin(), pos_.end(), - [](const IdRelType::PosType& lhs, const IdRelType::PosType& rhs) { return lhs.pos() < rhs.pos(); }); -} - } // namespace reindexer diff --git a/cpp_src/core/ft/idrelset.h b/cpp_src/core/ft/idrelset.h index 05ea5f8b7..23bc811fa 100644 --- a/cpp_src/core/ft/idrelset.h +++ b/cpp_src/core/ft/idrelset.h @@ -102,11 +102,11 @@ class IdRelType { addField(field); } void SortAndUnique() { - boost::sort::pdqsort(pos_.begin(), pos_.end()); + boost::sort::pdqsort_branchless(pos_.begin(), pos_.end()); auto last = std::unique(pos_.begin(), pos_.end()); pos_.resize(last - pos_.begin()); } - void Clear() { + void Clear() noexcept { usedFieldsMask_ = 0; #ifdef REINDEXER_FT_EXTRA_DEBUG pos_.clear(); @@ -116,7 +116,11 @@ class IdRelType { } size_t Size() const noexcept { return pos_.size(); } size_t size() const noexcept { return pos_.size(); } - void SimpleCommit(); + void SimpleCommit() noexcept { + boost::sort::pdqsort_branchless( + pos_.begin(), pos_.end(), + [](const IdRelType::PosType& lhs, const IdRelType::PosType& rhs) noexcept { return lhs.pos() < rhs.pos(); }); + } const RVector& Pos() const noexcept { return pos_; } uint64_t UsedFieldsMask() const noexcept { return usedFieldsMask_; } size_t HeapSize() const noexcept { return heapSize(pos_); } @@ -141,7 +145,7 @@ class IdRelType { class IdRelSet : public std::vector { public: int Add(VDocIdType id, int pos, int field); - void SimpleCommit() { + void SimpleCommit() noexcept { for (auto& val : *this) val.SimpleCommit(); } diff --git a/cpp_src/core/ft/numtotext.cc b/cpp_src/core/ft/numtotext.cc index fc91c1848..44fe81df2 100644 --- a/cpp_src/core/ft/numtotext.cc +++ b/cpp_src/core/ft/numtotext.cc @@ -45,8 +45,9 @@ static std::string_view getNumorder(int numorder, int i) { return sextillion[i]; case Septillion: return septillion[i]; + default: + throw Error(errParams, "Incorrect order [%s]: too big", numorder); } - throw Error(errParams, "Incorrect order [%s]: too big", numorder); } RX_ALWAYS_INLINE int ansiCharacterToDigit(char ch) noexcept { return static_cast(ch - 48); } @@ -73,6 +74,8 @@ static std::vector getOrders(std::string_view str) { tempString += numStr[i + 1]; tempString += numStr[i]; break; + default: + throw Error(errLogic, "Unexpected lost characters number: %d", lostChars); } } orders.emplace_back(std::move(tempString)); diff --git a/cpp_src/core/idset.h b/cpp_src/core/idset.h index 81522fcef..e2e501c00 100644 --- a/cpp_src/core/idset.h +++ b/cpp_src/core/idset.h @@ -108,7 +108,7 @@ class IdSet : public IdSetPlain { return *this; } static Ptr BuildFromUnsorted(base_idset &&ids) { - boost::sort::pdqsort(ids.begin(), ids.end()); + boost::sort::pdqsort_branchless(ids.begin(), ids.end()); ids.erase(std::unique(ids.begin(), ids.end()), ids.end()); // TODO: It would be better to integrate unique into sort return make_intrusive>(std::move(ids)); } diff --git a/cpp_src/core/index/indextext/fastindextext.cc b/cpp_src/core/index/indextext/fastindextext.cc index 12cbdcae9..c56dc44b8 100644 --- a/cpp_src/core/index/indextext/fastindextext.cc +++ b/cpp_src/core/index/indextext/fastindextext.cc @@ -123,7 +123,7 @@ template IndexMemStat FastIndexText::GetMemStat(const RdxContext &ctx) { auto ret = IndexUnordered::GetMemStat(ctx); - contexted_shared_lock lck(this->mtx_, &ctx); + contexted_shared_lock lck(this->mtx_, ctx); ret.fulltextSize = this->holder_->GetMemStat(); ret.idsetCache = this->cache_ft_ ? this->cache_ft_->GetMemStat() : LRUCacheMemStat(); return ret; diff --git a/cpp_src/core/index/keyentry.h b/cpp_src/core/index/keyentry.h index 079f543c6..9c500dba1 100644 --- a/cpp_src/core/index/keyentry.h +++ b/cpp_src/core/index/keyentry.h @@ -33,12 +33,14 @@ class KeyEntry { auto idsAsc = Sorted(ctx.getCurSortId()); size_t idx = 0; + const auto& ids2Sorts = ctx.ids2Sorts(); + [[maybe_unused]] const IdType maxRowId = IdType(ids2Sorts.size()); // For all ids of current key for (auto rowid : ids_) { - assertf(rowid < int(ctx.ids2Sorts().size()), "id=%d,ctx.ids2Sorts().size()=%d", rowid, ctx.ids2Sorts().size()); - idsAsc[idx++] = ctx.ids2Sorts()[rowid]; + assertf(rowid < maxRowId, "id=%d,ctx.ids2Sorts().size()=%d", rowid, maxRowId); + idsAsc[idx++] = ids2Sorts[rowid]; } - boost::sort::pdqsort(idsAsc.begin(), idsAsc.end()); + boost::sort::pdqsort_branchless(idsAsc.begin(), idsAsc.end()); } void Dump(std::ostream& os, std::string_view step, std::string_view offset) const { std::string newOffset; diff --git a/cpp_src/core/index/rtree/greenesplitter.h b/cpp_src/core/index/rtree/greenesplitter.h index ba707e781..c8c6a7179 100644 --- a/cpp_src/core/index/rtree/greenesplitter.h +++ b/cpp_src/core/index/rtree/greenesplitter.h @@ -1,6 +1,7 @@ #pragma once #include "splitter.h" +#include "vendor/sort/pdqsort.hpp" namespace reindexer { @@ -53,7 +54,7 @@ class GreeneSplitter : private Splitter secondSeedBoundRect.Left() + secondSeedBoundRect.Right()) { std::swap(seeds.first, seeds.second); } - std::sort(std::begin(indexes), std::end(indexes), [&src, this](size_t lhs, size_t rhs) { + boost::sort::pdqsort(std::begin(indexes), std::end(indexes), [&src, this](size_t lhs, size_t rhs) { return Base::getBoundRect(lhs < MaxEntries ? src[lhs] : this->appendingEntry_).Left() < Base::getBoundRect(rhs < MaxEntries ? src[rhs] : this->appendingEntry_).Left(); }); @@ -61,7 +62,7 @@ class GreeneSplitter : private Splitter secondSeedBoundRect.Bottom() + secondSeedBoundRect.Top()) { std::swap(seeds.first, seeds.second); } - std::sort(std::begin(indexes), std::end(indexes), [&src, this](size_t lhs, size_t rhs) { + boost::sort::pdqsort(std::begin(indexes), std::end(indexes), [&src, this](size_t lhs, size_t rhs) { return Base::getBoundRect(lhs < MaxEntries ? src[lhs] : this->appendingEntry_).Bottom() < Base::getBoundRect(rhs < MaxEntries ? src[rhs] : this->appendingEntry_).Bottom(); }); diff --git a/cpp_src/core/index/rtree/rstarsplitter.h b/cpp_src/core/index/rtree/rstarsplitter.h index a44c9748e..427a4add3 100644 --- a/cpp_src/core/index/rtree/rstarsplitter.h +++ b/cpp_src/core/index/rtree/rstarsplitter.h @@ -1,6 +1,7 @@ #pragma once #include "splitter.h" +#include "vendor/sort/pdqsort.hpp" namespace reindexer { @@ -19,12 +20,12 @@ class RStarSplitter : private SplitterOpts().IsSparse() || static_cast(fieldIndex_) >= ns.payloadType_.NumFields()) + ? ns.indexes_[fieldIndex_]->Fields().size() + : ns.payloadType_.Field(fieldIndex_).JsonPaths().size(); + + if (jsonPathsSize != 1) { + throw Error(errParams, "Ambiguity when updating field with several json paths by index name: '%s'", entry_.Column()); + } + if (!entry.IsExpression()) { const auto &fields{ns.indexes_[fieldIndex_]->Fields()}; if (fields.size() != 1) { @@ -126,11 +134,7 @@ ItemModifier::FieldData::FieldData(const UpdateEntry &entry, NamespaceImpl &ns) tagsPath_ = IndexedTagsPath{fields.getTagsPath(0)}; } } else { - const auto &fld{ns.payloadType_.Field(fieldIndex_)}; - for (const auto &jp : fld.JsonPaths()) { - tagsPath_ = ns.tagsMatcher_.path2indexedtag(jp, nullptr, true); - if (!tagsPath_.empty()) break; - } + tagsPath_ = ns.tagsMatcher_.path2indexedtag(ns.payloadType_.Field(fieldIndex_).JsonPaths()[0], nullptr, true); } if (tagsPath_.empty()) { throw Error(errParams, "Cannot find field by json: '%s'", entry_.Column()); @@ -467,7 +471,6 @@ void ItemModifier::modifyField(IdType itemId, FieldData &field, Payload &pl, Var tupleValue = tupleIdx->Upsert(item.GetField(0), itemId, needClearCache); if (needClearCache && tupleIdx->IsOrdered()) indexesCacheCleaner.Add(tupleIdx->SortId()); pl.Set(0, std::move(tupleValue)); - ns_.tagsMatcher_.try_merge(item.tagsMatcher()); if (exception) { std::rethrow_exception(exception); } @@ -575,6 +578,26 @@ void ItemModifier::modifyIndexValues(IdType itemId, const FieldData &field, Vari } else { pl.Get(field.index(), ns_.skrefs, true); } + + // Required when updating index array field with several tagpaths + VariantArray concatValues; + int offset = -1, length = -1; + pl.GetIndexedArrayData(field.tagspathWithLastIndex(), field.index(), offset, length); + const bool kConcatIndexValues = + index.Opts().IsArray() && !updateArrayPart && + (length < int(ns_.skrefs.size())); // (length < int(ns_.skrefs.size()) - condition to avoid coping + // when length and ns_.skrefs.size() are equal; then concatValues == values + if (kConcatIndexValues) { + if (offset < 0 || length < 0) { + concatValues = ns_.skrefs; + concatValues.insert(concatValues.end(), values.begin(), values.end()); + } else { + concatValues.insert(concatValues.end(), ns_.skrefs.begin(), ns_.skrefs.begin() + offset); + concatValues.insert(concatValues.end(), values.begin(), values.end()); + concatValues.insert(concatValues.end(), ns_.skrefs.begin() + offset + length, ns_.skrefs.end()); + } + } + if (!ns_.skrefs.empty()) { bool needClearCache{false}; rollBackIndexData_.IndexChanged(field.index(), index.Opts().IsPK()); @@ -584,7 +607,7 @@ void ItemModifier::modifyIndexValues(IdType itemId, const FieldData &field, Vari bool needClearCache{false}; rollBackIndexData_.IndexChanged(field.index(), index.Opts().IsPK()); - index.Upsert(ns_.krefs, values, itemId, needClearCache); + index.Upsert(ns_.krefs, kConcatIndexValues ? concatValues : values, itemId, needClearCache); if (needClearCache && index.IsOrdered()) indexesCacheCleaner.Add(index.SortId()); if (!index.Opts().IsSparse()) { pl.Set(field.index(), ns_.krefs); diff --git a/cpp_src/core/key_value_type.h b/cpp_src/core/key_value_type.h index 31c58a873..251627268 100644 --- a/cpp_src/core/key_value_type.h +++ b/cpp_src/core/key_value_type.h @@ -83,7 +83,7 @@ class KeyValueType { Composite, Tuple, Uuid - } value_; + } value_{KVT::Undefined}; constexpr explicit KeyValueType(KVT v) noexcept : value_{v} {} [[nodiscard]] static KeyValueType fromNumber(int n) { @@ -144,8 +144,9 @@ class KeyValueType { case TAG_ARRAY: case TAG_OBJECT: case TAG_END: - throw Error(errParams, "Invalid tag type value for KeyValueType: " + std::string{TagTypeToStr(t)}); + break; } + throw Error(errParams, "Invalid tag type value for KeyValueType: " + std::string{TagTypeToStr(t)}); } template diff --git a/cpp_src/core/keyvalue/variant.h b/cpp_src/core/keyvalue/variant.h index 6496c928b..efdf304ed 100644 --- a/cpp_src/core/keyvalue/variant.h +++ b/cpp_src/core/keyvalue/variant.h @@ -3,7 +3,6 @@ #include "core/indexopts.h" #include "core/key_value_type.h" #include "estl/h_vector.h" -#include "tools/errors.h" namespace reindexer { @@ -256,6 +255,15 @@ class VariantArray : public h_vector { static VariantArray Create(Ts &&...vs) { return VariantArray{Variant{std::forward(vs)}...}; } + template + static VariantArray Create(std::initializer_list vs) { + VariantArray res; + res.reserve(vs.size()); + for (auto &v : vs) { + res.emplace_back(std::move(v)); + } + return res; + } void Clear() noexcept { clear(); isArrayValue = false; diff --git a/cpp_src/core/lsn.cc b/cpp_src/core/lsn.cc index dc88fb059..73c0130e2 100644 --- a/cpp_src/core/lsn.cc +++ b/cpp_src/core/lsn.cc @@ -3,9 +3,11 @@ namespace reindexer { -void lsn_t::GetJSON(JsonBuilder &builder) const { +void lsn_t::GetJSON(JsonBuilder& builder) const { builder.Put("server_id", Server()); builder.Put("counter", Counter()); } -} // namespace reindexer +[[noreturn]] void lsn_t::throwValidation(ErrorCode code, const char* fmt, int64_t value) { throw Error(code, fmt, value); } + +} // namespace reindexer \ No newline at end of file diff --git a/cpp_src/core/lsn.h b/cpp_src/core/lsn.h index eb1f83d15..174540da4 100644 --- a/cpp_src/core/lsn.h +++ b/cpp_src/core/lsn.h @@ -13,58 +13,53 @@ class JsonBuilder; // SSS NNN NNN NNN NNN NNN (18 decimal digits) struct lsn_t { - static const int64_t digitCountLSNMult = 1000000000000000ll; +private: + static constexpr int16_t kMinServerIDValue = 0; + static constexpr int16_t kMaxServerIDValue = 999; - static const int64_t kCounterbitCount = 48; - static const int64_t kCounterMask = (1ull << kCounterbitCount) - 1ull; + static constexpr int64_t kMaxCounter = 1000000000000000ll; + static constexpr int64_t kDefaultCounter = kMaxCounter - 1; +public: void GetJSON(JsonBuilder &builder) const; void FromJSON(const gason::JsonNode &root) { - int server = root["server_id"].As(0); - int64_t counter = root["counter"].As(digitCountLSNMult - 1ll); + const int server = root["server_id"].As(0); + const int64_t counter = root["counter"].As(kDefaultCounter); payload_ = int64_t(lsn_t(counter, server)); } - lsn_t() {} - explicit lsn_t(int64_t v) { - if ((v & kCounterMask) == kCounterMask) // init -1 - payload_ = digitCountLSNMult - 1ll; - else { - payload_ = v; - } - } - lsn_t(int64_t counter, uint8_t server) { - if ((counter & kCounterMask) == kCounterMask) counter = digitCountLSNMult - 1ll; - int64_t s = server * digitCountLSNMult; - payload_ = s + counter; + lsn_t() noexcept = default; + lsn_t(const lsn_t &) noexcept = default; + lsn_t(lsn_t &&) noexcept = default; + lsn_t &operator=(const lsn_t &) noexcept = default; + lsn_t &operator=(lsn_t &&) noexcept = default; + explicit lsn_t(int64_t v) : lsn_t(v % kMaxCounter, v / kMaxCounter) {} + lsn_t(int64_t counter, int16_t server) { + validateCounter(counter); + validateServerId(server); + payload_ = server * kMaxCounter + counter; } explicit operator int64_t() const { return payload_; } - bool operator==(lsn_t o) { return payload_ == o.payload_; } - bool operator!=(lsn_t o) { return payload_ != o.payload_; } + bool operator==(lsn_t o) const noexcept { return payload_ == o.payload_; } + bool operator!=(lsn_t o) const noexcept { return payload_ != o.payload_; } - int64_t SetServer(short s) { - if (s > 999) throw Error(errLogic, "Server id > 999"); - int64_t server = s * digitCountLSNMult; - int64_t serverOld = payload_ / digitCountLSNMult; - payload_ = payload_ - serverOld * digitCountLSNMult + server; + int64_t SetServer(short server) { + validateServerId(server); + payload_ = server * kMaxCounter + Counter(); return payload_; } - int64_t SetCounter(int64_t c) { - if (c >= digitCountLSNMult) throw Error(errLogic, "LSN Counter > digitCountLSNMult"); - int64_t server = payload_ / digitCountLSNMult; - payload_ = server * digitCountLSNMult + c; + int64_t SetCounter(int64_t counter) { + validateCounter(counter); + payload_ = Server() * kMaxCounter + counter; return payload_; } - int64_t Counter() const { - int64_t server = payload_ / digitCountLSNMult; - return payload_ - server * digitCountLSNMult; - } - short Server() const { return payload_ / digitCountLSNMult; } - bool isEmpty() const { return Counter() == digitCountLSNMult - 1ll; } + int64_t Counter() const noexcept { return payload_ % kMaxCounter; } + int16_t Server() const noexcept { return payload_ / kMaxCounter; } + bool isEmpty() const noexcept { return Counter() == kDefaultCounter; } - int compare(lsn_t o) { + int compare(lsn_t o) const { if (Server() != o.Server()) throw Error(errLogic, "Compare lsn from different server"); if (Counter() < o.Counter()) return -1; @@ -73,13 +68,28 @@ struct lsn_t { return 0; } - bool operator<(lsn_t o) { return compare(o) == -1; } - bool operator<=(lsn_t o) { return compare(o) <= 0; } - bool operator>(lsn_t o) { return compare(o) == 1; } - bool operator>=(lsn_t o) { return compare(o) >= 0; } + bool operator<(lsn_t o) const { return compare(o) == -1; } + bool operator<=(lsn_t o) const { return compare(o) <= 0; } + bool operator>(lsn_t o) const { return compare(o) == 1; } + bool operator>=(lsn_t o) const { return compare(o) >= 0; } + +private: + int64_t payload_ = kDefaultCounter; + static void validateServerId(int16_t server) { + if (server < kMinServerIDValue) { + throwValidation(errLogic, "Server id < %d", kMinServerIDValue); + } + if (server > kMaxServerIDValue) { + throwValidation(errLogic, "Server id > %d", kMaxServerIDValue); + } + } + static void validateCounter(int64_t counter) { + if (counter > kDefaultCounter) { + throwValidation(errLogic, "LSN Counter > Default LSN (%d)", kMaxCounter); + } + } -protected: - int64_t payload_ = digitCountLSNMult - 1ll; + [[noreturn]] static void throwValidation(ErrorCode, const char *, int64_t); }; struct LSNPair { diff --git a/cpp_src/core/namespace/namespace.cc b/cpp_src/core/namespace/namespace.cc index 733bb309e..01632f4f8 100644 --- a/cpp_src/core/namespace/namespace.cc +++ b/cpp_src/core/namespace/namespace.cc @@ -1,14 +1,11 @@ #include "namespace.h" #include "core/querystat.h" -#include "core/storage/storagefactory.h" #include "tools/flagguard.h" #include "tools/fsops.h" #include "tools/logger.h" namespace reindexer { -#define handleInvalidation(Fn) nsFuncWrapper - void Namespace::CommitTransaction(Transaction& tx, QueryResults& result, const RdxContext& ctx) { auto nsl = atomicLoadMainNs(); bool enablePerfCounters = nsl->enablePerfCounters_.load(std::memory_order_relaxed); @@ -23,7 +20,7 @@ void Namespace::CommitTransaction(Transaction& tx, QueryResults& result, const R if (needNamespaceCopy(nsl, tx)) { PerfStatCalculatorMT calc(nsl->updatePerfCounter_, enablePerfCounters); - auto lck = statCalculator.CreateLock(clonerMtx_, &ctx); + auto lck = statCalculator.CreateLock(clonerMtx_, ctx); nsl = ns_; if (needNamespaceCopy(nsl, tx)) { @@ -76,11 +73,11 @@ void Namespace::CommitTransaction(Transaction& tx, QueryResults& result, const R return; } } - handleInvalidation(NamespaceImpl::CommitTransaction)(tx, result, NsContext(ctx), statCalculator); + nsFuncWrapper<&NamespaceImpl::CommitTransaction>(tx, result, NsContext(ctx), statCalculator); } NamespacePerfStat Namespace::GetPerfStat(const RdxContext& ctx) { - NamespacePerfStat stats = handleInvalidation(NamespaceImpl::GetPerfStat)(ctx); + NamespacePerfStat stats = nsFuncWrapper<&NamespaceImpl::GetPerfStat>(ctx); stats.transactions = txStatsCounter_.Get(); auto copyStats = copyStatsCounter_.Get(); stats.transactions.totalCopyCount = copyStats.totalHitCount; @@ -107,7 +104,7 @@ bool Namespace::needNamespaceCopy(const NamespaceImpl::Ptr& ns, const Transactio void Namespace::doRename(const Namespace::Ptr& dst, const std::string& newName, const std::string& storagePath, const RdxContext& ctx) { std::string dbpath; const auto flushOpts = StorageFlushOpts().WithImmediateReopen(); - auto lck = handleInvalidation(NamespaceImpl::wLock)(ctx); + auto lck = nsFuncWrapper<&NamespaceImpl::wLock>(ctx); auto srcNsPtr = atomicLoadMainNs(); auto& srcNs = *srcNsPtr; srcNs.storage_.Flush(flushOpts); // Repeat flush, to raise any disk errors before attempt to close storage diff --git a/cpp_src/core/namespace/namespace.h b/cpp_src/core/namespace/namespace.h index 55dc59548..012f0856e 100644 --- a/cpp_src/core/namespace/namespace.h +++ b/cpp_src/core/namespace/namespace.h @@ -5,13 +5,82 @@ #include "bgnamespacedeleter.h" #include "core/querystat.h" #include "core/txstats.h" -#include "estl/shared_mutex.h" namespace reindexer { -#define handleInvalidation(Fn) nsFuncWrapper - class Namespace { + template + auto nsFuncWrapper(Args &&...args) const { + while (true) { + try { + auto ns = atomicLoadMainNs(); + return (*ns.*fn)(std::forward(args)...); + } catch (const Error &e) { + if (e.code() != errNamespaceInvalidated) { + throw; + } else { + std::this_thread::yield(); + } + } + } + } + + template + void nsFuncWrapper(Item &item, QueryResults &qr, NsContext ctx) const { + nsFuncWrapper(item, qr, ctx); + } + + template + void nsFuncWrapper(const Query &query, QueryResults &qr, NsContext ctx) const { + nsFuncWrapper(query, qr, ctx); + } + + template + void nsFuncWrapper(T &v, QueryResults &qr, NsContext ctx) const { + while (true) { + NamespaceImpl::Ptr ns; + bool added = false; + try { + ns = atomicLoadMainNs(); + PerfStatCalculatorMT calc(ns->updatePerfCounter_, ns->enablePerfCounters_); + CounterGuardAIR32 cg(ns->cancelCommitCnt_); + if constexpr (std::is_same_v) { + auto locker{ns->wLock(ctx.rdxContext)}; + calc.LockHit(); + cg.Reset(); + ns->checkApplySlaveUpdate(ctx.rdxContext.fromReplication_); + qr.AddNamespace(ns, true); + added = true; + (*ns.*fn)(v, enumVal, ctx); + qr.AddItem(v, true, false); + ns->tryForceFlush(std::move(locker)); + } else if constexpr (std::is_same_v) { + auto params = longUpdDelLoggingParams_.load(std::memory_order_relaxed); + const bool isEnabled = params.thresholdUs >= 0 && !isSystemNamespaceNameFast(v.NsName()); + auto statCalculator = QueryStatCalculator(long_actions::MakeLogger(v, std::move(params)), isEnabled); + auto locker = statCalculator.CreateLock(*ns, &NamespaceImpl::wLock, ctx.rdxContext); + calc.LockHit(); + cg.Reset(); + ns->checkApplySlaveUpdate(ctx.rdxContext.fromReplication_); + qr.AddNamespace(ns, true); + added = true; + (*ns.*fn)(v, qr, ctx); + statCalculator.LogFlushDuration(*ns, &NamespaceImpl::tryForceFlush, std::move(locker)); + } else { + static_assert(std::is_same_v || std::is_same_v); + } + return; + } catch (const Error &e) { + if (e.code() != errNamespaceInvalidated) { + throw; + } else { + if (added) qr.RemoveNamespace(ns.get()); + std::this_thread::yield(); + } + } + } + } + public: using Ptr = shared_ptr; @@ -19,103 +88,95 @@ class Namespace { : ns_(make_intrusive(name, observers)), bgDeleter_(bgDeleter) {} void CommitTransaction(Transaction &tx, QueryResults &result, const RdxContext &ctx); - std::string GetName(const RdxContext &ctx) const { return handleInvalidation(NamespaceImpl::GetName)(ctx); } - bool IsSystem(const RdxContext &ctx) const { return handleInvalidation(NamespaceImpl::IsSystem)(ctx); } - bool IsTemporary(const RdxContext &ctx) const { return handleInvalidation(NamespaceImpl::IsTemporary)(ctx); } + std::string GetName(const RdxContext &ctx) const { return nsFuncWrapper<&NamespaceImpl::GetName>(ctx); } + bool IsSystem(const RdxContext &ctx) const { return nsFuncWrapper<&NamespaceImpl::IsSystem>(ctx); } + bool IsTemporary(const RdxContext &ctx) const { return nsFuncWrapper<&NamespaceImpl::IsTemporary>(ctx); } void EnableStorage(const std::string &path, StorageOpts opts, StorageType storageType, const RdxContext &ctx) { - handleInvalidation(NamespaceImpl::EnableStorage)(path, opts, storageType, ctx); + nsFuncWrapper<&NamespaceImpl::EnableStorage>(path, opts, storageType, ctx); } void LoadFromStorage(unsigned threadsCount, const RdxContext &ctx) { - handleInvalidation(NamespaceImpl::LoadFromStorage)(threadsCount, ctx); + nsFuncWrapper<&NamespaceImpl::LoadFromStorage>(threadsCount, ctx); } - void DeleteStorage(const RdxContext &ctx) { handleInvalidation(NamespaceImpl::DeleteStorage)(ctx); } - uint32_t GetItemsCount() { return handleInvalidation(NamespaceImpl::GetItemsCount)(); } - void AddIndex(const IndexDef &indexDef, const RdxContext &ctx) { handleInvalidation(NamespaceImpl::AddIndex)(indexDef, ctx); } - void UpdateIndex(const IndexDef &indexDef, const RdxContext &ctx) { handleInvalidation(NamespaceImpl::UpdateIndex)(indexDef, ctx); } - void DropIndex(const IndexDef &indexDef, const RdxContext &ctx) { handleInvalidation(NamespaceImpl::DropIndex)(indexDef, ctx); } - void SetSchema(std::string_view schema, const RdxContext &ctx) { handleInvalidation(NamespaceImpl::SetSchema)(schema, ctx); } - std::string GetSchema(int format, const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::GetSchema)(format, ctx); } - std::shared_ptr GetSchemaPtr(const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::GetSchemaPtr)(ctx); } - void Insert(Item &item, const RdxContext &ctx) { handleInvalidation(NamespaceImpl::Insert)(item, ctx); } + void DeleteStorage(const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::DeleteStorage>(ctx); } + uint32_t GetItemsCount() { return nsFuncWrapper<&NamespaceImpl::GetItemsCount>(); } + void AddIndex(const IndexDef &indexDef, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::AddIndex>(indexDef, ctx); } + void UpdateIndex(const IndexDef &indexDef, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::UpdateIndex>(indexDef, ctx); } + void DropIndex(const IndexDef &indexDef, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::DropIndex>(indexDef, ctx); } + void SetSchema(std::string_view schema, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::SetSchema>(schema, ctx); } + std::string GetSchema(int format, const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::GetSchema>(format, ctx); } + std::shared_ptr GetSchemaPtr(const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::GetSchemaPtr>(ctx); } + void Insert(Item &item, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::Insert>(item, ctx); } void Insert(Item &item, QueryResults &qr, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::modifyItem, ItemModifyMode::ModeInsert>(item, qr, ctx); } - void Update(Item &item, const RdxContext &ctx) { - nsFuncWrapper(item, ctx); - } + void Update(Item &item, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::Update>(item, ctx); } void Update(Item &item, QueryResults &qr, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::modifyItem, ItemModifyMode::ModeUpdate>(item, qr, ctx); } void Update(const Query &query, QueryResults &result, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::doUpdate, QueryType::QueryUpdate>(query, result, ctx); } - void Upsert(Item &item, const RdxContext &ctx) { handleInvalidation(NamespaceImpl::Upsert)(item, ctx); } + void Upsert(Item &item, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::Upsert>(item, ctx); } void Upsert(Item &item, QueryResults &qr, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::modifyItem, ItemModifyMode::ModeUpsert>(item, qr, ctx); } - void Delete(Item &item, const RdxContext &ctx) { - nsFuncWrapper(item, ctx); - } + void Delete(Item &item, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::Delete>(item, ctx); } void Delete(Item &item, QueryResults &qr, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::modifyItem, ItemModifyMode::ModeDelete>(item, qr, ctx); } void Delete(const Query &query, QueryResults &result, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::doDelete, QueryType::QueryDelete>(query, result, ctx); } - void Truncate(const RdxContext &ctx) { handleInvalidation(NamespaceImpl::Truncate)(ctx); } + void Truncate(const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::Truncate>(ctx); } void Select(QueryResults &result, SelectCtx ¶ms, const RdxContext &ctx) { - handleInvalidation(NamespaceImpl::Select)(result, params, ctx); + nsFuncWrapper<&NamespaceImpl::Select>(result, params, ctx); } - NamespaceDef GetDefinition(const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::GetDefinition)(ctx); } - NamespaceMemStat GetMemStat(const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::GetMemStat)(ctx); } + NamespaceDef GetDefinition(const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::GetDefinition>(ctx); } + NamespaceMemStat GetMemStat(const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::GetMemStat>(ctx); } NamespacePerfStat GetPerfStat(const RdxContext &ctx); void ResetPerfStat(const RdxContext &ctx) { txStatsCounter_.Reset(); commitStatsCounter_.Reset(); copyStatsCounter_.Reset(); - handleInvalidation(NamespaceImpl::ResetPerfStat)(ctx); + nsFuncWrapper<&NamespaceImpl::ResetPerfStat>(ctx); } - std::vector EnumMeta(const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::EnumMeta)(ctx); } + std::vector EnumMeta(const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::EnumMeta>(ctx); } void BackgroundRoutine(RdxActivityContext *ctx) { if (hasCopy_.load(std::memory_order_acquire)) { return; } - handleInvalidation(NamespaceImpl::BackgroundRoutine)(ctx); + nsFuncWrapper<&NamespaceImpl::BackgroundRoutine>(ctx); } void StorageFlushingRoutine() { if (hasCopy_.load(std::memory_order_acquire)) { return; } - handleInvalidation(NamespaceImpl::StorageFlushingRoutine)(); + nsFuncWrapper<&NamespaceImpl::StorageFlushingRoutine>(); } - void CloseStorage(const RdxContext &ctx) { handleInvalidation(NamespaceImpl::CloseStorage)(ctx); } - Transaction NewTransaction(const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::NewTransaction)(ctx); } + void CloseStorage(const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::CloseStorage>(ctx); } + Transaction NewTransaction(const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::NewTransaction>(ctx); } - Item NewItem(const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::NewItem)(ctx); } - void ToPool(ItemImpl *item) { handleInvalidation(NamespaceImpl::ToPool)(item); } - std::string GetMeta(const std::string &key, const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::GetMeta)(key, ctx); } + Item NewItem(const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::NewItem>(ctx); } + void ToPool(ItemImpl *item) { nsFuncWrapper<&NamespaceImpl::ToPool>(item); } + std::string GetMeta(const std::string &key, const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::GetMeta>(key, ctx); } void PutMeta(const std::string &key, std::string_view data, const RdxContext &ctx) { - handleInvalidation(NamespaceImpl::PutMeta)(key, data, ctx); + nsFuncWrapper<&NamespaceImpl::PutMeta>(key, data, ctx); } - int64_t GetSerial(const std::string &field) { return handleInvalidation(NamespaceImpl::GetSerial)(field); } - int getIndexByName(std::string_view index) const { - return nsFuncWrapper(index); - } - bool getIndexByName(std::string_view name, int &index) const { - return nsFuncWrapper(name, index); - } - void FillResult(QueryResults &result, const IdSet &ids) const { handleInvalidation(NamespaceImpl::FillResult)(result, ids); } - void EnablePerfCounters(bool enable = true) { handleInvalidation(NamespaceImpl::EnablePerfCounters)(enable); } - ReplicationState GetReplState(const RdxContext &ctx) const { return handleInvalidation(NamespaceImpl::GetReplState)(ctx); } - void SetReplLSNs(LSNPair LSNs, const RdxContext &ctx) { handleInvalidation(NamespaceImpl::SetReplLSNs)(LSNs, ctx); } + int64_t GetSerial(const std::string &field) { return nsFuncWrapper<&NamespaceImpl::GetSerial>(field); } + int getIndexByName(std::string_view index) const { return nsFuncWrapper<&NamespaceImpl::getIndexByName>(index); } + bool getIndexByName(std::string_view name, int &index) const { return nsFuncWrapper<&NamespaceImpl::tryGetIndexByName>(name, index); } + void FillResult(QueryResults &result, const IdSet &ids) const { nsFuncWrapper<&NamespaceImpl::FillResult>(result, ids); } + void EnablePerfCounters(bool enable = true) { nsFuncWrapper<&NamespaceImpl::EnablePerfCounters>(enable); } + ReplicationState GetReplState(const RdxContext &ctx) const { return nsFuncWrapper<&NamespaceImpl::GetReplState>(ctx); } + void SetReplLSNs(LSNPair LSNs, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::SetReplLSNs>(LSNs, ctx); } void SetSlaveReplStatus(ReplicationState::Status status, const Error &error, const RdxContext &ctx) { - handleInvalidation(NamespaceImpl::SetSlaveReplStatus)(status, error, ctx); + nsFuncWrapper<&NamespaceImpl::SetSlaveReplStatus>(status, error, ctx); } void SetSlaveReplMasterState(MasterState state, const RdxContext &ctx) { - handleInvalidation(NamespaceImpl::SetSlaveReplMasterState)(state, ctx); + nsFuncWrapper<&NamespaceImpl::SetSlaveReplMasterState>(state, ctx); } Error ReplaceTagsMatcher(const TagsMatcher &tm, const RdxContext &ctx) { - return handleInvalidation(NamespaceImpl::ReplaceTagsMatcher)(tm, ctx); + return nsFuncWrapper<&NamespaceImpl::ReplaceTagsMatcher>(tm, ctx); } void Rename(const Namespace::Ptr &dst, const std::string &storagePath, const RdxContext &ctx) { if (this == dst.get() || dst == nullptr) { @@ -142,25 +203,28 @@ class Namespace { txSizeToAlwaysCopy_.store(configData.txSizeToAlwaysCopy, std::memory_order_relaxed); longTxLoggingParams_.store(configProvider.GetTxLoggingParams(), std::memory_order_relaxed); longUpdDelLoggingParams_.store(configProvider.GetUpdDelLoggingParams(), std::memory_order_relaxed); - handleInvalidation(NamespaceImpl::OnConfigUpdated)(configProvider, ctx); + nsFuncWrapper<&NamespaceImpl::OnConfigUpdated>(configProvider, ctx); + } + StorageOpts GetStorageOpts(const RdxContext &ctx) { return nsFuncWrapper<&NamespaceImpl::GetStorageOpts>(ctx); } + void Refill(std::vector &items, const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::Refill>(items, ctx); } + void SetTagsMatcher(TagsMatcher &&tm, const RdxContext &ctx) { + return nsFuncWrapper<&NamespaceImpl::SetTagsMatcher>(std::move(tm), ctx); } - StorageOpts GetStorageOpts(const RdxContext &ctx) { return handleInvalidation(NamespaceImpl::GetStorageOpts)(ctx); } - void Refill(std::vector &items, const RdxContext &ctx) { handleInvalidation(NamespaceImpl::Refill)(items, ctx); } void DumpIndex(std::ostream &os, std::string_view index, const RdxContext &ctx) { - return handleInvalidation(NamespaceImpl::DumpIndex)(os, index, ctx); + return nsFuncWrapper<&NamespaceImpl::DumpIndex>(os, index, ctx); } - void SetDestroyFlag() { return handleInvalidation(NamespaceImpl::SetDestroyFlag)(); } + void SetDestroyFlag() { return nsFuncWrapper<&NamespaceImpl::SetDestroyFlag>(); } protected: friend class ReindexerImpl; friend class QueryResults; - void updateSelectTime() const { handleInvalidation(NamespaceImpl::updateSelectTime)(); } - void setSlaveMode(const RdxContext &ctx) { handleInvalidation(NamespaceImpl::setSlaveMode)(ctx); } + void updateSelectTime() const { nsFuncWrapper<&NamespaceImpl::updateSelectTime>(); } + void setSlaveMode(const RdxContext &ctx) { nsFuncWrapper<&NamespaceImpl::setSlaveMode>(ctx); } NamespaceImpl::Ptr getMainNs() const { return atomicLoadMainNs(); } NamespaceImpl::Ptr awaitMainNs(const RdxContext &ctx) const { if (hasCopy_.load(std::memory_order_acquire)) { - contexted_unique_lock lck(clonerMtx_, &ctx); + contexted_unique_lock lck(clonerMtx_, ctx); assertrx(!hasCopy_.load(std::memory_order_acquire)); return ns_; } @@ -168,77 +232,6 @@ class Namespace { } private: - template - typename std::invoke_result::type nsFuncWrapper(Args &&...args) const { - while (true) { - try { - auto ns = atomicLoadMainNs(); - return (*ns.*fn)(std::forward(args)...); - } catch (const Error &e) { - if (e.code() != errNamespaceInvalidated) { - throw; - } else { - std::this_thread::yield(); - } - } - } - } - - template - void nsFuncWrapper(Item &item, QueryResults &qr, NsContext ctx) const { - nsFuncWrapper(item, qr, ctx); - } - - template - void nsFuncWrapper(const Query &query, QueryResults &qr, NsContext ctx) const { - nsFuncWrapper(query, qr, - ctx); - } - - template , ItemModifyMode, QueryType> enumVal> - void nsFuncWrapper(T &v, QueryResults &qr, NsContext ctx) const { - while (true) { - NamespaceImpl::Ptr ns; - bool added = false; - try { - ns = atomicLoadMainNs(); - PerfStatCalculatorMT calc(ns->updatePerfCounter_, ns->enablePerfCounters_); - CounterGuardAIR32 cg(ns->cancelCommitCnt_); - if constexpr (std::is_same_v) { - auto locker{ns->wLock(ctx.rdxContext)}; - calc.LockHit(); - cg.Reset(); - ns->checkApplySlaveUpdate(ctx.rdxContext.fromReplication_); - qr.AddNamespace(ns, true); - added = true; - (*ns.*fn)(v, enumVal, ctx); - qr.AddItem(v, true, false); - ns->tryForceFlush(std::move(locker)); - } else if constexpr (std::is_same_v) { - auto params = longUpdDelLoggingParams_.load(std::memory_order_relaxed); - const bool isEnabled = params.thresholdUs >= 0 && !isSystemNamespaceNameFast(v.NsName()); - auto statCalculator = QueryStatCalculator(long_actions::MakeLogger(v, std::move(params)), isEnabled); - auto locker = statCalculator.CreateLock(*ns, &NamespaceImpl::wLock, ctx.rdxContext); - calc.LockHit(); - cg.Reset(); - ns->checkApplySlaveUpdate(ctx.rdxContext.fromReplication_); - qr.AddNamespace(ns, true); - added = true; - (*ns.*fn)(v, qr, ctx); - statCalculator.LogFlushDuration(*ns, &NamespaceImpl::tryForceFlush, std::move(locker)); - } - return; - } catch (const Error &e) { - if (e.code() != errNamespaceInvalidated) { - throw; - } else { - if (added) qr.RemoveNamespace(ns.get()); - std::this_thread::yield(); - } - } - } - } - bool needNamespaceCopy(const NamespaceImpl::Ptr &ns, const Transaction &tx) const noexcept; void doRename(const Namespace::Ptr &dst, const std::string &newName, const std::string &storagePath, const RdxContext &ctx); NamespaceImpl::Ptr atomicLoadMainNs() const { @@ -267,6 +260,4 @@ class Namespace { BackgroundNamespaceDeleter &bgDeleter_; }; -#undef handleInvalidation - } // namespace reindexer diff --git a/cpp_src/core/namespace/namespaceimpl.cc b/cpp_src/core/namespace/namespaceimpl.cc index ef58a7116..4c254163e 100644 --- a/cpp_src/core/namespace/namespaceimpl.cc +++ b/cpp_src/core/namespace/namespaceimpl.cc @@ -358,8 +358,10 @@ class NamespaceImpl::RollBack_recreateCompositeIndexes : private RollBackBase { if (idx->HoldsStrings()) { ns_.strHolder_->Add(std::move(idx)); } + // NOLINTBEGIN(bugprone-empty-catch) } catch (...) { } + // NOLINTEND(bugprone-empty-catch) } } void RollBack() noexcept { @@ -657,6 +659,7 @@ void NamespaceImpl::SetSchema(std::string_view schema, const RdxContext& ctx) { } } + const auto initTmVer = tagsMatcher_.version(); schema_ = std::make_shared(schema); auto fields = schema_->GetPaths(); for (auto& field : fields) { @@ -667,6 +670,19 @@ void NamespaceImpl::SetSchema(std::string_view schema, const RdxContext& ctx) { saveSchemaToStorage(); addToWAL(schema, WalSetSchema, ctx); + if (initTmVer != tagsMatcher_.version()) { + const lsn_t lsn(wal_.Add(WALRecord(WalEmpty), lsn_t()), serverId_); + if (!ctx.fromReplication_) repl_.lastSelfLSN = lsn; + if (!repl_.temporary) { + WrSerializer wser; + wser.PutVarint(tagsMatcher_.version()); + wser.PutVarint(tagsMatcher_.stateToken()); + tagsMatcher_.serialize(wser); + // This record is matter for the online replication only + observers_->OnWALUpdate(LSNPair(lsn, ctx.fromReplication_ ? ctx.LSNs_.originLSN_ : lsn), name_, + WALRecord(WalTagsMatcher, wser.Slice())); + } + } } std::string NamespaceImpl::GetSchema(int format, const RdxContext& ctx) { @@ -789,7 +805,7 @@ void NamespaceImpl::verifyCompositeIndex(const IndexDef& indexDef) const { } for (const auto& jp : indexDef.jsonPaths_) { int idx; - if (!getIndexByName(jp, idx)) { + if (!tryGetIndexByName(jp, idx)) { if (!IsFullText(indexDef.Type())) { throw Error(errParams, "Composite indexes over non-indexed field ('%s') are not supported yet (except for full-text indexes). Create " @@ -924,14 +940,18 @@ class NamespaceImpl::RollBack_insertIndex : private RollBackBase { if (insertedIdxName_) { try { ns_.indexesNames_.erase(*insertedIdxName_); + // NOLINTBEGIN(bugprone-empty-catch) } catch (...) { } + // NOLINTEND(bugprone-empty-catch) } if (pkIndexNameInserted_) { try { ns_.indexesNames_.erase(kPKIndexName); + // NOLINTBEGIN(bugprone-empty-catch) } catch (...) { } + // NOLINTEND(bugprone-empty-catch) } for (auto& n : ns_.indexesNames_) { if (n.second > insertedIdxNo_) { @@ -940,8 +960,10 @@ class NamespaceImpl::RollBack_insertIndex : private RollBackBase { } try { ns_.indexes_.erase(insertedIndex_); + // NOLINTBEGIN(bugprone-empty-catch) } catch (...) { } + // NOLINTEND(bugprone-empty-catch) Disable(); } void PkIndexNameInserted() noexcept { pkIndexNameInserted_ = true; } @@ -1219,7 +1241,7 @@ int NamespaceImpl::getIndexByName(std::string_view index) const { int NamespaceImpl::getIndexByNameOrJsonPath(std::string_view index) const { int idx; - if (getIndexByName(index, idx)) { + if (tryGetIndexByName(index, idx)) { return idx; } idx = payloadType_.FieldByJsonPath(index); @@ -1232,7 +1254,7 @@ int NamespaceImpl::getIndexByNameOrJsonPath(std::string_view index) const { int NamespaceImpl::getScalarIndexByName(std::string_view index) const { int idx; - if (getIndexByName(index, idx)) { + if (tryGetIndexByName(index, idx)) { if (idx < indexes_.firstCompositePos()) { return idx; } @@ -1240,7 +1262,7 @@ int NamespaceImpl::getScalarIndexByName(std::string_view index) const { throw Error(errParams, "Index '%s' not found in '%s'", index, name_); } -bool NamespaceImpl::getIndexByName(std::string_view name, int& index) const { +bool NamespaceImpl::tryGetIndexByName(std::string_view name, int& index) const { auto it = indexesNames_.find(name); if (it == indexesNames_.end()) return false; index = it->second; @@ -1248,7 +1270,7 @@ bool NamespaceImpl::getIndexByName(std::string_view name, int& index) const { } bool NamespaceImpl::getIndexByNameOrJsonPath(std::string_view name, int& index) const { - if (getIndexByName(name, index)) { + if (tryGetIndexByName(name, index)) { return true; } const auto idx = payloadType_.FieldByJsonPath(name); @@ -1261,7 +1283,7 @@ bool NamespaceImpl::getIndexByNameOrJsonPath(std::string_view name, int& index) bool NamespaceImpl::getScalarIndexByName(std::string_view name, int& index) const { int idx; - if (getIndexByName(name, idx)) { + if (tryGetIndexByName(name, idx)) { if (idx < indexes_.firstCompositePos()) { index = idx; return true; @@ -1346,8 +1368,7 @@ void NamespaceImpl::doUpdate(const Query& query, QueryResults& result, const NsC if (statementReplication) { WrSerializer ser; - const_cast(query).type_ = QueryUpdate; - WALRecord wrec(WalUpdateQuery, query.GetSQL(ser).Slice(), ctx.inTransaction); + WALRecord wrec(WalUpdateQuery, query.GetSQL(ser, QueryUpdate).Slice(), ctx.inTransaction); lsn_t lsn(wal_.Add(wrec), serverId_); if (!ctx.rdxContext.fromReplication_) repl_.lastSelfLSN = lsn; for (ItemRef& item : result.Items()) { @@ -1358,7 +1379,7 @@ void NamespaceImpl::doUpdate(const Query& query, QueryResults& result, const NsC if (!ctx.rdxContext.fromReplication_) setReplLSNs(LSNPair(lsn_t(), lsn)); } - if (query.debugLevel >= LogInfo) { + if (query.GetDebugLevel() >= LogInfo) { logPrintf(LogInfo, "Updated %d items in %d µs", result.Count(), duration_cast(high_resolution_clock::now() - tmStart).count()); } @@ -1499,9 +1520,9 @@ void NamespaceImpl::doDelete(IdType id) { markUpdated(true); } -void NamespaceImpl::doDelete(const Query& q, QueryResults& result, const NsContext& ctx) { +void NamespaceImpl::doDelete(const Query& query, QueryResults& result, const NsContext& ctx) { NsSelecter selecter(this); - SelectCtx selCtx(q, nullptr); + SelectCtx selCtx(query, nullptr); selCtx.contextCollectingMode = true; selCtx.requiresCrashTracking = true; selCtx.inTransaction = ctx.inTransaction; @@ -1510,7 +1531,7 @@ void NamespaceImpl::doDelete(const Query& q, QueryResults& result, const NsConte selCtx.functions = &func; selecter(result, selCtx, ctx.rdxContext); - ActiveQueryScope queryScope(q, QueryDelete, optimizationState_, strHolder_.get()); + ActiveQueryScope queryScope(query, QueryDelete, optimizationState_, strHolder_.get()); assertrx(result.IsNamespaceAdded(this)); const auto tmStart = high_resolution_clock::now(); @@ -1522,10 +1543,9 @@ void NamespaceImpl::doDelete(const Query& q, QueryResults& result, const NsConte doDelete(r.Id()); } - if (!q.HasLimit() && !q.HasOffset() && result.Count() >= kWALStatementItemsThreshold) { + if (!query.HasLimit() && !query.HasOffset() && result.Count() >= kWALStatementItemsThreshold) { WrSerializer ser; - const_cast(q).type_ = QueryDelete; - WALRecord wrec(WalUpdateQuery, q.GetSQL(ser).Slice(), ctx.inTransaction); + WALRecord wrec(WalUpdateQuery, query.GetSQL(ser, QueryDelete).Slice(), ctx.inTransaction); processWalRecord(wrec, ctx.rdxContext); } else { WrSerializer cjson; @@ -1537,7 +1557,7 @@ void NamespaceImpl::doDelete(const Query& q, QueryResults& result, const NsConte processWalRecord(wrec, ctx.rdxContext); } } - if (q.debugLevel >= LogInfo) { + if (query.GetDebugLevel() >= LogInfo) { logPrintf(LogInfo, "Deleted %d items in %d µs", result.Count(), duration_cast(high_resolution_clock::now() - tmStart).count()); } @@ -1698,20 +1718,41 @@ void NamespaceImpl::CommitTransaction(Transaction& tx, QueryResults& result, NsC storageAdvice = storage_.AdviceBatching(); } - for (auto& step : tx.GetSteps()) { - if (step.query_) { - QueryResults qr; - qr.AddNamespace(this, true); - if (step.query_->type_ == QueryDelete) { - doDelete(*step.query_, qr, ctx); - } else { - doUpdate(*step.query_, qr, ctx); + for (auto&& step : tx.GetSteps()) { + switch (step.type_) { + case TransactionStep::Type::ModifyItem: { + const auto mode = std::get(step.data_).mode; + Item item = tx.GetItem(std::move(step)); + modifyItem(item, mode, ctx); + result.AddItem(item); + break; } - } else { - const auto modifyMode = step.modifyMode_; - Item item = tx.GetItem(std::move(step)); - modifyItem(item, modifyMode, ctx); - result.AddItem(item); + case TransactionStep::Type::Query: { + QueryResults qr; + qr.AddNamespace(this, true); + auto& data = std::get(step.data_); + if (data.query->type_ == QueryDelete) { + doDelete(*data.query, qr, ctx); + } else { + doUpdate(*data.query, qr, ctx); + } + break; + } + case TransactionStep::Type::Nop: + break; + case TransactionStep::Type::PutMeta: { + auto& data = std::get(step.data_); + putMeta(data.key, data.value, ctx.rdxContext); + break; + } + case TransactionStep::Type::SetTM: { + auto& data = std::get(step.data_); + auto tmCopy = data.tm; + setTagsMatcher(std::move(tmCopy), ctx); + break; + } + default: + std::abort(); } } @@ -1810,7 +1851,7 @@ void NamespaceImpl::doUpsert(ItemImpl* ritem, IdType id, bool doUpdate) { } else { pl.Get(field, krefs, index.Opts().IsArray()); } - if (krefs == skrefs) continue; + if ((krefs.ArrayType().Is() && skrefs.ArrayType().Is()) || krefs == skrefs) continue; bool needClearCache{false}; index.Delete(krefs, id, *strHolder_, needClearCache); if (needClearCache && index.IsOrdered()) indexesCacheCleaner.Add(index.SortId()); @@ -2567,6 +2608,11 @@ std::shared_ptr NamespaceImpl::GetSchemaPtr(const RdxContext& ctx) return schema_; } +void NamespaceImpl::SetTagsMatcher(TagsMatcher&& tm, const RdxContext& ctx) { + auto wlck = wLock(ctx); + setTagsMatcher(std::move(tm), ctx); +} + void NamespaceImpl::LoadFromStorage(unsigned threadsCount, const RdxContext& ctx) { auto wlck = wLock(ctx); FlagGuardT nsLoadingGuard(nsIsLoading_); @@ -2624,7 +2670,8 @@ void NamespaceImpl::removeExpiredItems(RdxActivityContext* ctx) { index->GetTTLValue(); QueryResults qr; qr.AddNamespace(this, true); - doDelete(Query(name_).Where(index->Name(), CondLt, expirationthreshold), qr, rdxCtx); + auto q = Query(name_).Where(index->Name(), CondLt, expirationthreshold); + doDelete(q, qr, rdxCtx); } tryForceFlush(std::move(wlck)); } @@ -2647,6 +2694,31 @@ void NamespaceImpl::removeExpiredStrings(RdxActivityContext* ctx) { } } +void NamespaceImpl::setTagsMatcher(TagsMatcher&& tm, const NsContext& ctx) { + // NOTE: In v4 tm tokens here are always the same, but in v3 those tokens are not synchronized. Probably it should workd anyway + // if (tm.stateToken() != tagsMatcher_.stateToken()) { + // throw Error(errParams, "Tagsmatcher have different statetokens: %08X vs %08X", tagsMatcher_.stateToken(), tm.stateToken()); + // } + if (!ctx.rdxContext.fromReplication_) { + throw Error(errParams, "Tagsmatcher can be set from replication only"); + } + tagsMatcher_ = tm; + tagsMatcher_.UpdatePayloadType(payloadType_, false); + tagsMatcher_.setUpdated(); + + const lsn_t lsn(wal_.Add(WALRecord(WalEmpty, 0, ctx.inTransaction)), serverId_); + if (!repl_.temporary) { + WrSerializer ser; + ser.PutVarint(tagsMatcher_.version()); + ser.PutVarint(tagsMatcher_.stateToken()); + tagsMatcher_.serialize(ser); + observers_->OnWALUpdate(LSNPair(lsn, ctx.rdxContext.LSNs_.originLSN_), name_, + WALRecord(WalTagsMatcher, ser.Slice(), ctx.inTransaction)); + } + + saveTagsMatcherToStorage(true); +} + void NamespaceImpl::BackgroundRoutine(RdxActivityContext* ctx) { const RdxContext rdxCtx(ctx); const NsContext nsCtx(rdxCtx); diff --git a/cpp_src/core/namespace/namespaceimpl.h b/cpp_src/core/namespace/namespaceimpl.h index 31a6e8fb4..f05ab9b76 100644 --- a/cpp_src/core/namespace/namespaceimpl.h +++ b/cpp_src/core/namespace/namespaceimpl.h @@ -134,11 +134,12 @@ class NamespaceImpl : public intrusive_atomic_rc_base { // NOLINT(*performance. friend SortExpression; friend SortExprFuncs::DistanceBetweenJoinedIndexesSameNs; friend class ReindexerImpl; + friend class RxSelector; friend QueryResults; friend class ItemsLoader; friend class IndexInserters; - class NSUpdateSortedContext : public UpdateSortedContext { + class NSUpdateSortedContext final : public UpdateSortedContext { public: NSUpdateSortedContext(const NamespaceImpl &ns, SortType curSortId) : ns_(ns), sorted_indexes_(ns_.getSortedIdxCount()), curSortId_(curSortId) { @@ -259,7 +260,7 @@ class NamespaceImpl : public intrusive_atomic_rc_base { // NOLINT(*performance. int getIndexByName(std::string_view index) const; int getIndexByNameOrJsonPath(std::string_view name) const; int getScalarIndexByName(std::string_view name) const; - bool getIndexByName(std::string_view name, int &index) const; + bool tryGetIndexByName(std::string_view name, int &index) const; bool getIndexByNameOrJsonPath(std::string_view name, int &index) const; bool getScalarIndexByName(std::string_view name, int &index) const; bool getSparseIndexByJsonPath(std::string_view jsonPath, int &index) const; @@ -282,6 +283,9 @@ class NamespaceImpl : public intrusive_atomic_rc_base { // NOLINT(*performance. std::shared_ptr GetSchemaPtr(const RdxContext &ctx) const; int getNsNumber() const { return schema_ ? schema_->GetProtobufNsNumber() : 0; } IndexesCacheCleaner GetIndexesCacheCleaner() { return IndexesCacheCleaner{*this}; } + // Separate method for the v3/v4 replication compatibility. + // It should not be used outside of this scenario + void SetTagsMatcher(TagsMatcher &&tm, const RdxContext &ctx); void SetDestroyFlag() { dbDestroyed_ = true; } Error FlushStorage(const RdxContext &ctx) { const auto flushOpts = StorageFlushOpts().WithImmediateReopen(); @@ -303,10 +307,10 @@ class NamespaceImpl : public intrusive_atomic_rc_base { // NOLINT(*performance. typedef contexted_shared_lock RLockT; typedef contexted_unique_lock WLockT; - RLockT RLock(const RdxContext &ctx) const { return RLockT(mtx_, &ctx); } + RLockT RLock(const RdxContext &ctx) const { return RLockT(mtx_, ctx); } WLockT WLock(const RdxContext &ctx) const { using namespace std::string_view_literals; - WLockT lck(mtx_, &ctx); + WLockT lck(mtx_, ctx); if (readonly_.load(std::memory_order_acquire)) { throw Error(errNamespaceInvalidated, "NS invalidated"sv); } @@ -373,6 +377,7 @@ class NamespaceImpl : public intrusive_atomic_rc_base { // NOLINT(*performance. std::optional &&modifyData); void removeExpiredItems(RdxActivityContext *); void removeExpiredStrings(RdxActivityContext *); + void setTagsMatcher(TagsMatcher &&tm, const NsContext &ctx); Item newItem(); template diff --git a/cpp_src/core/nsselecter/explaincalc.cc b/cpp_src/core/nsselecter/explaincalc.cc index 484efe308..642cade9c 100644 --- a/cpp_src/core/nsselecter/explaincalc.cc +++ b/cpp_src/core/nsselecter/explaincalc.cc @@ -29,7 +29,8 @@ void ExplainCalc::LogDump(int logLevel) { [this](const FieldsComparator &c) { logPrintf(LogInfo, "%s: cost %g, matched %d, %s", c.Name(), c.Cost(iters_), c.GetMatchedCount(), c.Dump()); }, - [](const AlwaysFalse &) { logPrintf(LogInfo, "AlwaysFalse"); }); + [](const AlwaysFalse &) { logPrintf(LogInfo, "AlwaysFalse"); }, + [](const AlwaysTrue &) { logPrintf(LogInfo, "AlwaysTrue"); }); } if (jselectors_) { @@ -192,6 +193,7 @@ std::string ExplainCalc::GetJSON() { WrSerializer ser; { JsonBuilder json(ser); + json.EmitTrailingForFloat(false); if (enabled_) { json.Put("total_us"sv, To_us(total_)); json.Put("preselect_us"sv, To_us(preselect_)); @@ -290,6 +292,13 @@ std::string SelectIteratorContainer::explainJSON(const_iterator begin, const_ite jsonSkiped.Put("description"sv, "always "s + (it->operation == OpNot ? "true" : "false")); name << opName(it->operation == OpNot ? OpAnd : it->operation, it == begin) << "Always"sv << (it->operation == OpNot ? "True"sv : "False"sv); + }, + [&](const AlwaysTrue &) { + auto jsonSkiped = builder.Object(); + jsonSkiped.Put("type"sv, "Skipped"sv); + jsonSkiped.Put("description"sv, "always "s + (it->operation == OpNot ? "false" : "true")); + name << opName(it->operation == OpNot ? OpAnd : it->operation, it == begin) << "Always"sv + << (it->operation == OpNot ? "False"sv : "True"sv); }); } name << ')'; diff --git a/cpp_src/core/nsselecter/joinedselector.cc b/cpp_src/core/nsselecter/joinedselector.cc index 7492f23a5..5d13089cb 100644 --- a/cpp_src/core/nsselecter/joinedselector.cc +++ b/cpp_src/core/nsselecter/joinedselector.cc @@ -31,7 +31,7 @@ void JoinedSelector::selectFromRightNs(QueryResults &joinItemR, const Query &que ctx.skipIndexesLookup = true; ctx.functions = &selectFunctions_; rightNs_->Select(joinItemR, ctx, rdxCtx_); - if (query.explain_) { + if (query.GetExplain()) { preResult_->explainOneSelect = joinItemR.explainResults; } @@ -54,7 +54,7 @@ void JoinedSelector::selectFromPreResultValues(QueryResults &joinItemR, const Qu for (const ItemRef &item : preResult_->values) { auto &v = item.Value(); assertrx(!v.IsFree()); - if (query.entries.CheckIfSatisfyConditions({preResult_->values.payloadType, v})) { + if (query.Entries().CheckIfSatisfyConditions({preResult_->values.payloadType, v})) { if (++matched > query.Limit()) break; found = true; joinItemR.Add(item); @@ -73,21 +73,21 @@ bool JoinedSelector::Process(IdType rowId, int nsId, ConstPayload payload, bool const auto startTime = ExplainCalc::Clock::now(); // Put values to join conditions size_t i = 0; - if (itemQuery_.explain_ && !preResult_->explainOneSelect.empty()) itemQuery_.explain_ = false; + if (itemQuery_.GetExplain() && !preResult_->explainOneSelect.empty()) itemQuery_.Explain(false); std::unique_ptr itemQueryCopy; Query *itemQueryPtr = &itemQuery_; for (auto &je : joinQuery_.joinEntries_) { - QueryEntry &qentry = itemQueryPtr->entries.Get(i); + QueryEntry &qentry = itemQueryPtr->GetUpdatableEntry(i); { auto keyValues = qentry.UpdatableValues(QueryEntry::IgnoreEmptyValues{}); payload.GetByFieldsSet(je.LeftFields(), keyValues, je.LeftFieldType(), je.LeftCompositeFieldsTypes()); } if (qentry.Values().empty()) { if (itemQueryPtr == &itemQuery_) { - itemQueryCopy = std::unique_ptr{new Query(itemQuery_)}; + itemQueryCopy = std::make_unique(itemQuery_); itemQueryPtr = itemQueryCopy.get(); } - itemQueryPtr->entries.SetValue(i, AlwaysFalse{}); + itemQueryPtr->SetEntry(i); } ++i; } @@ -188,7 +188,7 @@ void JoinedSelector::AppendSelectIteratorOfJoinIndexData(SelectIteratorContainer return; } unsigned optimized = 0; - assertrx_throw(preResult_->dataMode != JoinPreResult::ModeValues || itemQuery_.entries.Size() == joinQuery_.joinEntries_.size()); + assertrx_throw(preResult_->dataMode != JoinPreResult::ModeValues || itemQuery_.Entries().Size() == joinQuery_.joinEntries_.size()); for (size_t i = 0; i < joinQuery_.joinEntries_.size(); ++i) { const QueryJoinEntry &joinEntry = joinQuery_.joinEntries_[i]; if (!joinEntry.IsLeftFieldIndexed() || joinEntry.Operation() != OpAnd || diff --git a/cpp_src/core/nsselecter/nsselecter.cc b/cpp_src/core/nsselecter/nsselecter.cc index 937707fb9..3a7c22bc0 100644 --- a/cpp_src/core/nsselecter/nsselecter.cc +++ b/cpp_src/core/nsselecter/nsselecter.cc @@ -23,12 +23,10 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte // std::cout << sql << std::endl; const size_t resultInitSize = result.Count(); ctx.sortingContext.enableSortOrders = ns_->SortOrdersBuilt(); - if (ns_->config_.logLevel > ctx.query.debugLevel) { - const_cast(&ctx.query)->debugLevel = ns_->config_.logLevel; - } + const LogLevel logLevel = std::max(ns_->config_.logLevel, LogLevel(ctx.query.GetDebugLevel())); auto &explain = ctx.explain; - explain = ExplainCalc(ctx.query.explain_ || ctx.query.debugLevel >= LogInfo); + explain = ExplainCalc(ctx.query.GetExplain() || logLevel >= LogInfo); ActiveQueryScope queryScope(ctx, ns_->optimizationState_, explain, ns_->locker_.IsReadOnly(), ns_->strHolder_.get()); explain.SetPreselectTime(ctx.preResultTimeTotal); @@ -65,15 +63,12 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte } OnConditionInjections explainInjectedOnConditions; - QueryPreprocessor qPreproc((ctx.preResult && ctx.preResult->executionMode == JoinPreResult::ModeExecute) - ? const_cast(&ctx.query.entries)->MakeLazyCopy() - : QueryEntries{ctx.query.entries}, - ns_, ctx); + QueryPreprocessor qPreproc(QueryEntries{ctx.query.Entries()}, ns_, ctx); if (ctx.joinedSelectors) { - qPreproc.InjectConditionsFromJoins(*ctx.joinedSelectors, explainInjectedOnConditions, rdxCtx); + qPreproc.InjectConditionsFromJoins(*ctx.joinedSelectors, explainInjectedOnConditions, logLevel, rdxCtx); explain.PutOnConditionInjections(&explainInjectedOnConditions); } - auto aggregators = getAggregators(aggregationQueryRef.aggregations_, aggregationQueryRef.strictMode); + auto aggregators = getAggregators(aggregationQueryRef.aggregations_, aggregationQueryRef.GetStrictMode()); qPreproc.AddDistinctEntries(aggregators); const bool aggregationsOnly = aggregators.size() > 1 || (aggregators.size() == 1 && aggregators[0].Type() != AggDistinct); @@ -106,7 +101,7 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte explain.AddPrepareTime(); if (ctx.contextCollectingMode) { - result.addNSContext(ns_->payloadType_, ns_->tagsMatcher_, FieldsSet(ns_->tagsMatcher_, ctx.query.selectFilter_), ns_->schema_); + result.addNSContext(ns_->payloadType_, ns_->tagsMatcher_, FieldsSet(ns_->tagsMatcher_, ctx.query.SelectFilters()), ns_->schema_); } if (isFt) result.haveRank = true; @@ -119,8 +114,8 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte } SelectIteratorContainer qres(ns_->payloadType_, &ctx); - QresExplainHolder qresHolder(qres, (explain.IsEnabled() || ctx.query.debugLevel >= LogTrace) ? QresExplainHolder::ExplainEnabled::Yes - : QresExplainHolder::ExplainEnabled::No); + QresExplainHolder qresHolder(qres, (explain.IsEnabled() || logLevel >= LogTrace) ? QresExplainHolder::ExplainEnabled::Yes + : QresExplainHolder::ExplainEnabled::No); LoopCtx lctx(qres, ctx, qPreproc, aggregators, explain); if (!ctx.query.forcedSortOrder_.empty() && !qPreproc.MoreThanOneEvaluation()) { ctx.isForceAll = true; @@ -182,7 +177,7 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte qres.Append(OpAnd, SelectIterator(std::move(res), false, pr, IteratorFieldKind::None)); } break; case JoinPreResult::ModeIterators: - qres.LazyAppend(ctx.preResult->iterators.begin(), ctx.preResult->iterators.end()); + qres.Append(ctx.preResult->iterators.begin(), ctx.preResult->iterators.end()); break; case JoinPreResult::ModeValues: assertrx(0); @@ -211,7 +206,7 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte !ctx.sortingContext.sortIndex()) // 2. We have sorted query, by unordered index || ctx.preResult->btreeIndexOptimizationEnabled) { // 3. We have btree-index that is not committed yet ctx.preResult->iterators.Append(qres.cbegin(), qres.cend()); - if rx_unlikely (ctx.query.debugLevel >= LogInfo) { + if rx_unlikely (logLevel >= LogInfo) { logPrintf(LogInfo, "Built preResult (expected %d iterations) with %d iterators, q='%s'", maxIterations, qres.Size(), ctx.query.GetSQL()); } @@ -246,9 +241,9 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte bool hasComparators = false; qres.ExecuteAppropriateForEach( - Skip{}, - [&hasComparators](const FieldsComparator &) { hasComparators = true; }, - [&hasComparators](const SelectIterator &it) { + Skip{}, + [&hasComparators](const FieldsComparator &) noexcept { hasComparators = true; }, + [&hasComparators](const SelectIterator &it) noexcept { if (it.comparators_.size()) hasComparators = true; }); @@ -280,7 +275,7 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte qres.CheckFirstQuery(); // Rewind all results iterators - qres.ExecuteAppropriateForEach(Skip{}, + qres.ExecuteAppropriateForEach(Skip{}, [reverse, maxIterations](SelectIterator &it) { it.Start(reverse, maxIterations); }); // Let iterators choose most effecive algorith @@ -325,7 +320,7 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte // Get total count for simple query with 1 condition and 1 idset if (needCalcTotal && !lctx.calcTotal) { - if (!ctx.query.entries.Empty()) { + if (!ctx.query.Entries().Empty()) { result.totalCount += qres.Get(0).GetMaxIterations(); } else { result.totalCount += ns_->items_.size() - ns_->free_.size(); @@ -361,7 +356,7 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte } } // Put count/count_cached to aggretions - if (aggregationQueryRef.CalcTotal() != ModeNoTotal || containAggCount || containAggCountCached) { + if (aggregationQueryRef.HasCalcTotal() || containAggCount || containAggCountCached) { AggregationResult ret; ret.fields = {"*"}; ret.type = (aggregationQueryRef.CalcTotal() == ModeAccurateTotal || containAggCount) ? AggCount : AggCountCached; @@ -386,18 +381,18 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte explain.PutSelectors(&qresHolder.GetResultsRef()); explain.PutJoinedSelectors(ctx.joinedSelectors); - if rx_unlikely (ctx.query.debugLevel >= LogInfo) { + if rx_unlikely (logLevel >= LogInfo) { logPrintf(LogInfo, "%s", ctx.query.GetSQL()); - explain.LogDump(ctx.query.debugLevel); + explain.LogDump(logLevel); } - if (ctx.query.explain_) { + if (ctx.query.GetExplain()) { if (ctx.preResult && ctx.preResult->executionMode == JoinPreResult::ModeBuild) { ctx.preResult->explainPreSelect = explain.GetJSON(); } else { result.explainResults = explain.GetJSON(); } } - if rx_unlikely (ctx.query.debugLevel >= LogTrace) { + if rx_unlikely (logLevel >= LogTrace) { logPrintf(LogInfo, "Query returned: [%s]; total=%d", result.Dump(), result.totalCount); } @@ -408,13 +403,13 @@ void NsSelecter::operator()(QueryResults &result, SelectCtx &ctx, const RdxConte if (ctx.preResult && ctx.preResult->executionMode == JoinPreResult::ModeBuild) { switch (ctx.preResult->dataMode) { case JoinPreResult::ModeIdSet: - if rx_unlikely (ctx.query.debugLevel >= LogInfo) { + if rx_unlikely (logLevel >= LogInfo) { logPrintf(LogInfo, "Built idset preResult (expected %d iterations) with %d ids, q = '%s'", explain.Iterations(), ctx.preResult->ids.size(), ctx.query.GetSQL()); } break; case JoinPreResult::ModeValues: - if rx_unlikely (ctx.query.debugLevel >= LogInfo) { + if rx_unlikely (logLevel >= LogInfo) { logPrintf(LogInfo, "Built values preResult (expected %d iterations) with %d values, q = '%s'", explain.Iterations(), ctx.preResult->values.size(), ctx.query.GetSQL()); } @@ -487,7 +482,7 @@ class NsSelecter::JoinedNsValueGetter { template It NsSelecter::applyForcedSort(It begin, It end, const ItemComparator &compare, const SelectCtx &ctx, const joins::NamespaceResults *jr) { assertrx_throw(!ctx.sortingContext.entries.empty()); - if (ctx.query.mergeQueries_.size() > 1) throw Error(errLogic, "Force sort could not be applied to 'merged' queries."); + if (ctx.query.GetMergeQueries().size() > 1) throw Error(errLogic, "Force sort could not be applied to 'merged' queries."); return std::visit(overloaded{ [](const SortingContext::ExpressionEntry &) -> It { throw Error(errLogic, "Force sort could not be performed by expression."); @@ -627,65 +622,64 @@ class ForcedSortMap { static_cast(*this)); } const auto &operator*() const { - return std::visit(overloaded{[](MultiMap::Iterator it) -> const auto &{ return *it; - } - , [](SingleTypeMap::const_iterator it) -> const auto & { return *it; }}, + return std::visit(overloaded{[](MultiMap::Iterator it) -> const auto & { return *it; }, + [](SingleTypeMap::const_iterator it) -> const auto & { return *it; }}, static_cast(*this)); -} -}; // namespace reindexer + } + }; public: -ForcedSortMap(Variant k, mapped_type v, size_t size) - : data_{k.Type().Is() || k.Type().Is() || k.Type().IsNumeric() - ? DataType{MultiMap{size}} - : DataType{SingleTypeMap{{}, k.Type()}}} { - std::visit(overloaded{[&](MultiMap &m) { m.insert(std::move(k), v); }, [&](SingleTypeMap &m) { m.emplace(std::move(k), v); }}, data_); -} -std::pair emplace(Variant k, mapped_type v) & { - return std::visit(overloaded{[&](MultiMap &m) { - const auto [iter, success] = m.insert(std::move(k), v); - return std::make_pair(Iterator{iter}, success); - }, - [&](SingleTypeMap &m) { - if (!m.type_.IsSame(k.Type())) { - throw Error{errQueryExec, "Items of different types in forced sort list"}; - } - const auto [iter, success] = m.emplace(std::move(k), v); - return std::make_pair(Iterator{iter}, success); - }}, - data_); -} -bool contain(const Variant &k) const { - return std::visit(overloaded{[&k](const MultiMap &m) { return m.find(k) != m.cend(); }, - [&k](const SingleTypeMap &m) { - if (!m.type_.IsSame(k.Type())) { - throw Error{errQueryExec, "Items of different types in forced sort list"}; - } - return m.find(k) != m.end(); - }}, - data_); -} -mapped_type get(const Variant &k) const { - return std::visit(overloaded{[&k](const MultiMap &m) { - const auto it = m.find(k); - assertrx_throw(it != m.cend()); - return it->second; - }, - [&k](const SingleTypeMap &m) { - if (!m.type_.IsSame(k.Type())) { - throw Error{errQueryExec, "Items of different types in forced sort list"}; - } - const auto it = m.find(k); - assertrx_throw(it != m.end()); - return it->second; - }}, - data_); -} + ForcedSortMap(Variant k, mapped_type v, size_t size) + : data_{k.Type().Is() || k.Type().Is() || k.Type().IsNumeric() + ? DataType{MultiMap{size}} + : DataType{SingleTypeMap{{}, k.Type()}}} { + std::visit(overloaded{[&](MultiMap &m) { m.insert(std::move(k), v); }, [&](SingleTypeMap &m) { m.emplace(std::move(k), v); }}, + data_); + } + std::pair emplace(Variant k, mapped_type v) & { + return std::visit(overloaded{[&](MultiMap &m) { + const auto [iter, success] = m.insert(std::move(k), v); + return std::make_pair(Iterator{iter}, success); + }, + [&](SingleTypeMap &m) { + if (!m.type_.IsSame(k.Type())) { + throw Error{errQueryExec, "Items of different types in forced sort list"}; + } + const auto [iter, success] = m.emplace(std::move(k), v); + return std::make_pair(Iterator{iter}, success); + }}, + data_); + } + bool contain(const Variant &k) const { + return std::visit(overloaded{[&k](const MultiMap &m) { return m.find(k) != m.cend(); }, + [&k](const SingleTypeMap &m) { + if (!m.type_.IsSame(k.Type())) { + throw Error{errQueryExec, "Items of different types in forced sort list"}; + } + return m.find(k) != m.end(); + }}, + data_); + } + mapped_type get(const Variant &k) const { + return std::visit(overloaded{[&k](const MultiMap &m) { + const auto it = m.find(k); + assertrx_throw(it != m.cend()); + return it->second; + }, + [&k](const SingleTypeMap &m) { + if (!m.type_.IsSame(k.Type())) { + throw Error{errQueryExec, "Items of different types in forced sort list"}; + } + const auto it = m.find(k); + assertrx_throw(it != m.end()); + return it->second; + }}, + data_); + } private: -DataType data_; -} -; + DataType data_; +}; template class ForcedMapInserter { @@ -886,7 +880,7 @@ It NsSelecter::applyForcedSortImpl(NamespaceImpl &ns, It begin, It end, const It template void NsSelecter::applyGeneralSort(It itFirst, It itLast, It itEnd, const ItemComparator &comparator, const SelectCtx &ctx) { - if (ctx.query.mergeQueries_.size() > 1) { + if (ctx.query.GetMergeQueries().size() > 1) { throw Error(errLogic, "Sorting cannot be applied to merged queries."); } @@ -1040,7 +1034,7 @@ void NsSelecter::selectLoop(LoopCtx &ctx, ResultsT &result, const RdxContext &rd // Exclude last sets of id from each query result, so duplicated keys will // be removed for (auto &it : qres) { - if (it.HoldsOrReferTo() && it.Value().distinct) { + if (it.Is() && it.Value().distinct) { it.Value().ExcludeLastSet(pv, rowId, properRowId); } } @@ -1214,7 +1208,7 @@ void NsSelecter::addSelectResult(uint8_t proc, IdType rowId, IdType properRowId, void NsSelecter::checkStrictModeAgg(StrictMode strictMode, const std::string &name, const std::string &nsName, const TagsMatcher &tagsMatcher) const { - if (int index = IndexValueType::SetByJsonPath; ns_->getIndexByName(name, index)) return; + if (int index = IndexValueType::SetByJsonPath; ns_->tryGetIndexByName(name, index)) return; if (strictMode == StrictModeIndexes) { throw Error(errParams, @@ -1351,8 +1345,9 @@ static void removeQuotesFromExpression(std::string &expression) { void NsSelecter::prepareSortingContext(SortingEntries &sortBy, SelectCtx &ctx, bool isFt, bool availableSelectBySortIndex) { using namespace SortExprFuncs; - const auto strictMode = - ctx.inTransaction ? StrictModeNone : ((ctx.query.strictMode == StrictModeNotSet) ? ns_->config_.strictMode : ctx.query.strictMode); + const auto strictMode = ctx.inTransaction + ? StrictModeNone + : ((ctx.query.GetStrictMode() == StrictModeNotSet) ? ns_->config_.strictMode : ctx.query.GetStrictMode()); static const JoinedSelectors emptyJoinedSelectors; const auto &joinedSelectors = ctx.joinedSelectors ? *ctx.joinedSelectors : emptyJoinedSelectors; ctx.sortingContext.entries.clear(); @@ -1401,7 +1396,7 @@ void NsSelecter::prepareSortingContext(SortingEntries &sortBy, SelectCtx &ctx, b ctx.isForceAll = true; } } else { - if (!ctx.query.mergeQueries_.empty()) { + if (!ctx.query.GetMergeQueries().empty()) { throw Error(errLogic, "Sorting by expression cannot be applied to merged queries."); } struct { @@ -1560,9 +1555,10 @@ size_t NsSelecter::calculateNormalCost(const QueryEntries &qentries, SelectCtx & next = qentries.Next(i); const bool calculateEntry = costCalculator.OnNewEntry(qentries, i, next); qentries.InvokeAppropriate( - i, Skip{}, [&costCalculator](const QueryEntriesBracket &) { costCalculator.MarkInapposite(); }, - [&costCalculator](const JoinQueryEntry &) { costCalculator.MarkInapposite(); }, - [&costCalculator](const BetweenFieldsQueryEntry &) { costCalculator.MarkInapposite(); }, + i, [](const SubQueryEntry &) { assertrx_throw(0); }, [](const SubQueryFieldEntry &) { assertrx_throw(0); }, + Skip{}, [&costCalculator](const QueryEntriesBracket &) noexcept { costCalculator.MarkInapposite(); }, + [&costCalculator](const JoinQueryEntry &) noexcept { costCalculator.MarkInapposite(); }, + [&costCalculator](const BetweenFieldsQueryEntry &) noexcept { costCalculator.MarkInapposite(); }, [&](const QueryEntry &qe) { if (!qe.IsFieldIndexed()) { costCalculator.MarkInapposite(); @@ -1627,9 +1623,11 @@ size_t NsSelecter::calculateOptimizedCost(size_t costNormal, const QueryEntries continue; } qentries.InvokeAppropriate( - i, Skip{}, [&costCalculator](const QueryEntriesBracket &) { costCalculator.MarkInapposite(); }, - [&costCalculator](const JoinQueryEntry &) { costCalculator.MarkInapposite(); }, - [&costCalculator](const BetweenFieldsQueryEntry &) { costCalculator.MarkInapposite(); }, + i, Skip{}, [](const SubQueryEntry &) { assertrx_throw(0); }, + [](const SubQueryFieldEntry &) { assertrx_throw(0); }, + [&costCalculator](const QueryEntriesBracket &) noexcept { costCalculator.MarkInapposite(); }, + [&costCalculator](const JoinQueryEntry &) noexcept { costCalculator.MarkInapposite(); }, + [&costCalculator](const BetweenFieldsQueryEntry &) noexcept { costCalculator.MarkInapposite(); }, [&](const QueryEntry &qe) { if (!qe.IsFieldIndexed() || qe.IndexNo() != ctx.sortingContext.uncommitedIndex) { costCalculator.MarkInapposite(); @@ -1659,7 +1657,7 @@ bool NsSelecter::isSortOptimizatonEffective(const QueryEntries &qentries, Select if (qentries.Size() == 0) { return true; } - if (qentries.Size() == 1 && qentries.HoldsOrReferTo(0)) { + if (qentries.Size() == 1 && qentries.Is(0)) { const auto &qe = qentries.Get(0); if (qe.IndexNo() == ctx.sortingContext.uncommitedIndex) { return SelectIteratorContainer::IsExpectingOrderedResults(qe); diff --git a/cpp_src/core/nsselecter/querypreprocessor.cc b/cpp_src/core/nsselecter/querypreprocessor.cc index 6070eb478..5eda4812a 100644 --- a/cpp_src/core/nsselecter/querypreprocessor.cc +++ b/cpp_src/core/nsselecter/querypreprocessor.cc @@ -19,7 +19,7 @@ QueryPreprocessor::QueryPreprocessor(QueryEntries &&queries, NamespaceImpl *ns, ns_(*ns), query_{ctx.query}, strictMode_(ctx.inTransaction ? StrictModeNone - : ((query_.strictMode == StrictModeNotSet) ? ns_.config_.strictMode : query_.strictMode)), + : ((query_.GetStrictMode() == StrictModeNotSet) ? ns_.config_.strictMode : query_.GetStrictMode())), start_(query_.Offset()), count_(query_.Limit()), forcedSortOrder_(!query_.forcedSortOrder_.empty()), @@ -54,7 +54,7 @@ void QueryPreprocessor::ExcludeFtQuery(const RdxContext &rdxCtx) { if (queryEntryAddedByForcedSortOptimization_ || Size() <= 1) return; for (auto it = begin(), next = it, endIt = end(); it != endIt; it = next) { ++next; - if (it->HoldsOrReferTo() && it->Value().IsFieldIndexed()) { + if (it->Is() && it->Value().IsFieldIndexed()) { auto &index = ns_.indexes_[it->Value().IndexNo()]; if (!IsFastFullText(index->Type())) continue; if (it->operation != OpAnd || (next != endIt && next->operation == OpOr) || !index->EnablePreselectBeforeFt()) break; @@ -119,9 +119,9 @@ void QueryPreprocessor::checkStrictMode(const QueryField &field) const { class JoinOnExplainEnabled; class JoinOnExplainDisabled; -void QueryPreprocessor::InjectConditionsFromJoins(JoinedSelectors &js, OnConditionInjections &expalainOnInjections, +void QueryPreprocessor::InjectConditionsFromJoins(JoinedSelectors &js, OnConditionInjections &expalainOnInjections, LogLevel logLevel, const RdxContext &rdxCtx) { - bool needExplain = query_.explain_ || query_.debugLevel >= LogInfo; + const bool needExplain = query_.GetExplain() || logLevel >= LogInfo; if (needExplain) { injectConditionsFromJoins(0, container_.size(), js, expalainOnInjections, rdxCtx); } else { @@ -176,7 +176,8 @@ size_t QueryPreprocessor::removeBrackets(size_t begin, size_t end) { void QueryPreprocessor::InitIndexNumbers() { ExecuteAppropriateForEach( - Skip{}, + Skip{}, [](const SubQueryEntry &) { assertrx(0); }, + [](const SubQueryFieldEntry &) { assertrx(0); }, [this](QueryEntry &entry) { if (!entry.FieldsHaveBeenSet()) { SetQueryField(entry.FieldData(), ns_); @@ -200,6 +201,14 @@ size_t QueryPreprocessor::lookupQueryIndexes(uint16_t dst, uint16_t srcBegin, ui for (size_t src = srcBegin, nextSrc; src < srcEnd; src = nextSrc) { nextSrc = Next(src); const bool changeDst = container_[src].InvokeAppropriate( + [](const SubQueryEntry &) -> bool { + assertrx_throw(0); + abort(); + }, + [](const SubQueryFieldEntry &) -> bool { + assertrx_throw(0); + abort(); + }, [&](const QueryEntriesBracket &) { if (dst != src) container_[dst] = std::move(container_[src]); const size_t mergedInBracket = lookupQueryIndexes(dst + 1, src + 1, nextSrc); @@ -242,6 +251,10 @@ size_t QueryPreprocessor::lookupQueryIndexes(uint16_t dst, uint16_t srcBegin, ui [dst, src, this](AlwaysFalse &) { if (dst != src) container_[dst] = std::move(container_[src]); return true; + }, + [dst, src, this](AlwaysTrue &) { + if (dst != src) container_[dst] = std::move(container_[src]); + return true; }); if (changeDst) dst = Next(dst); } @@ -250,20 +263,23 @@ size_t QueryPreprocessor::lookupQueryIndexes(uint16_t dst, uint16_t srcBegin, ui void QueryPreprocessor::CheckUniqueFtQuery() const { bool found = false; - ExecuteAppropriateForEach(Skip{}, [&](const QueryEntry &qe) { - if (qe.IsFieldIndexed() && IsFullText(ns_.indexes_[qe.IndexNo()]->Type())) { - if (found) { - throw Error{errQueryExec, "Query cannot contain more than one full text condition"}; - } else { - found = true; + ExecuteAppropriateForEach( + Skip{}, + [](const SubQueryEntry &) { assertrx_throw(0); }, [](const SubQueryFieldEntry &) { assertrx_throw(0); }, + [&](const QueryEntry &qe) { + if (qe.IsFieldIndexed() && IsFullText(ns_.indexes_[qe.IndexNo()]->Type())) { + if (found) { + throw Error{errQueryExec, "Query cannot contain more than one full text condition"}; + } else { + found = true; + } } - } - }); + }); } bool QueryPreprocessor::ContainsFullTextIndexes() const { for (auto it = cbegin().PlainIterator(), end = cend().PlainIterator(); it != end; ++it) { - if (it->HoldsOrReferTo() && it->Value().IsFieldIndexed() && + if (it->Is() && it->Value().IsFieldIndexed() && IsFullText(ns_.indexes_[it->Value().IndexNo()]->Type())) { return true; } @@ -331,7 +347,7 @@ size_t QueryPreprocessor::substituteCompositeIndexes(const size_t from, const si deleted += substituteCompositeIndexes(cur + 1, cur + bracketSize); continue; } - if (!HoldsOrReferTo(cur) || GetOperation(cur) != OpAnd) { + if (!Is(cur) || GetOperation(cur) != OpAnd) { continue; } const auto next = Next(cur); @@ -406,7 +422,8 @@ void QueryPreprocessor::convertWhereValues(QueryEntry &qe) const { qe.ConvertVal void QueryPreprocessor::convertWhereValues(QueryEntries::iterator begin, QueryEntries::iterator end) const { for (auto it = begin; it != end; ++it) { it->InvokeAppropriate( - Skip{}, + Skip{}, [](const SubQueryEntry &) { assertrx_throw(0); }, + [](const SubQueryFieldEntry &) { assertrx_throw(0); }, [this, &it](const QueryEntriesBracket &) { convertWhereValues(it.begin(), it.end()); }, [this](QueryEntry &qe) { convertWhereValues(qe); }); } @@ -445,6 +462,14 @@ void QueryPreprocessor::findMaxIndex(QueryEntries::const_iterator begin, QueryEn h_vector &foundIndexes) const { for (auto it = begin; it != end; ++it) { const FoundIndexInfo foundIdx = it->InvokeAppropriate( + [](const SubQueryEntry &) -> FoundIndexInfo { + assertrx_throw(0); + abort(); + }, + [](const SubQueryFieldEntry &) -> FoundIndexInfo { + assertrx_throw(0); + abort(); + }, [this, &it, &foundIndexes](const QueryEntriesBracket &) { findMaxIndex(it.cbegin(), it.cend(), foundIndexes); return FoundIndexInfo(); @@ -462,8 +487,9 @@ void QueryPreprocessor::findMaxIndex(QueryEntries::const_iterator begin, QueryEn } return FoundIndexInfo(); }, - [](const JoinQueryEntry &) { return FoundIndexInfo(); }, [](const BetweenFieldsQueryEntry &) { return FoundIndexInfo(); }, - [](const AlwaysFalse &) { return FoundIndexInfo(); }); + [](const JoinQueryEntry &) noexcept { return FoundIndexInfo(); }, + [](const BetweenFieldsQueryEntry &) noexcept { return FoundIndexInfo(); }, + [](const AlwaysFalse &) noexcept { return FoundIndexInfo(); }, [](const AlwaysTrue &) noexcept { return FoundIndexInfo(); }); if (foundIdx.index) { auto found = std::find_if(foundIndexes.begin(), foundIndexes.end(), [foundIdx](const FoundIndexInfo &i) { return i.index == foundIdx.index; }); @@ -484,10 +510,6 @@ bool QueryPreprocessor::mergeQueryEntries(size_t lhs, size_t rhs) { if rx_unlikely (lqe->Values().empty()) { return true; } - if (container_[lhs].IsRef()) { - container_[lhs].SetValue(const_cast(*lqe)); - lqe = &Get(lhs); - } const bool distinct = lqe->Distinct() || rqe.Distinct(); VariantArray setValues; if (rx_likely(!rqe.Values().empty())) { @@ -501,7 +523,7 @@ bool QueryPreprocessor::mergeQueryEntries(size_t lhs, size_t rhs) { constexpr size_t kMinArraySizeToUseHashSet = 250; if (second.size() < kMinArraySizeToUseHashSet) { // Intersect via binary search + sort for small vectors - std::sort(first.begin(), first.end()); + boost::sort::pdqsort(first.begin(), first.end()); for (auto &&v : second) { if (std::binary_search(first.begin(), first.end(), v)) { setValues.emplace_back(std::move(v)); @@ -527,20 +549,12 @@ bool QueryPreprocessor::mergeQueryEntries(size_t lhs, size_t rhs) { return true; } else if (rqe.Condition() == CondAny) { if (!lqe->Distinct() && rqe.Distinct()) { - if (container_[lhs].IsRef()) { - container_[lhs].SetValue(const_cast(*lqe)); - lqe = &Get(lhs); - } lqe->Distinct(true); } return true; } else if (lqe->Condition() == CondAny) { const bool distinct = lqe->Distinct() || rqe.Distinct(); - if (container_[rhs].IsRef()) { - container_[lhs].SetValue(const_cast(rqe)); - } else { - container_[lhs].SetValue(std::move(rqe)); - } + container_[lhs].SetValue(std::move(rqe)); Get(lhs).Distinct(distinct); return true; } @@ -572,7 +586,7 @@ std::pair QueryPreprocessor::queryValuesFromOnCondition( limit = std::min(std::max(rNsCfg.minPreselectSize, rightNs.ItemsCount() * rNsCfg.maxPreselectPart), rNsCfg.maxPreselectSize); } - joinQuery.explain_ = query_.explain_; + joinQuery.Explain(query_.GetExplain()); joinQuery.Limit(limit + 2); joinQuery.Offset(QueryEntry::kDefaultOffset); joinQuery.sortingEntries_.clear(); @@ -701,6 +715,7 @@ void QueryPreprocessor::briefDump(size_t from, size_t to, const std::vector ser << container_[it].operation << ' '; } container_[it].InvokeAppropriate( + [](const SubQueryEntry &) { assertrx_throw(0); }, [](const SubQueryFieldEntry &) { assertrx_throw(0); }, [&](const QueryEntriesBracket &b) { ser << "("; briefDump(it + 1, Next(it), joinedSelectors, ser); @@ -710,7 +725,7 @@ void QueryPreprocessor::briefDump(size_t from, size_t to, const std::vector [&ser](const QueryEntry &qe) { ser << qe.DumpBrief() << ' '; }, [&joinedSelectors, &ser](const JoinQueryEntry &jqe) { ser << jqe.Dump(joinedSelectors) << ' '; }, [&ser](const BetweenFieldsQueryEntry &qe) { ser << qe.Dump() << ' '; }, - [&ser](const AlwaysFalse &) { ser << "AlwaysFalse" << ' '; }); + [&ser](const AlwaysFalse &) { ser << "AlwaysFalse" << ' '; }, [&ser](const AlwaysTrue &) { ser << "AlwaysTrue" << ' '; }); } } } @@ -723,7 +738,8 @@ size_t QueryPreprocessor::injectConditionsFromJoins(size_t from, size_t to, Join size_t injectedCount = 0; for (size_t cur = from; cur < to; cur = Next(cur)) { container_[cur].InvokeAppropriate( - Skip{}, + [](const SubQueryEntry &) { assertrx_throw(0); }, [](const SubQueryFieldEntry &) { assertrx_throw(0); }, + Skip{}, [&](const QueryEntriesBracket &) { size_t injCount = injectConditionsFromJoins(cur + 1, Next(cur), js, explainOnInjections, rdxCtx); to += injCount; @@ -838,8 +854,8 @@ size_t QueryPreprocessor::injectConditionsFromJoins(size_t from, size_t to, Join CondType queryCondition{CondAny}; VariantArray values; if (byValues) { - assertrx_throw(joinedSelector.itemQuery_.entries.HoldsOrReferTo(i)); - assertrx_throw(joinedSelector.itemQuery_.entries.Get(i).FieldName() == joinEntry.RightFieldName()); + assertrx_throw(joinedSelector.itemQuery_.Entries().Is(i)); + assertrx_throw(joinedSelector.itemQuery_.Entries().Get(i).FieldName() == joinEntry.RightFieldName()); CollateOpts collate; if (joinEntry.IsLeftFieldIndexed()) { collate = ns_.indexes_[joinEntry.LeftIdxNo()]->Opts().collateOpts_; @@ -860,7 +876,7 @@ size_t QueryPreprocessor::injectConditionsFromJoins(size_t from, size_t to, Join case CondLe: case CondGt: case CondGe: - joinedSelector.itemQuery_.entries.Get(i).FieldType().EvaluateOneOf( + joinedSelector.itemQuery_.Entries().Get(i).FieldType().EvaluateOneOf( [&skip, &explainEntry](OneOf) noexcept { @@ -874,7 +890,7 @@ size_t QueryPreprocessor::injectConditionsFromJoins(size_t from, size_t to, Join case CondEq: case CondSet: case CondAllSet: - joinedSelector.itemQuery_.entries.Get(i).FieldType().EvaluateOneOf( + joinedSelector.itemQuery_.Entries().Get(i).FieldType().EvaluateOneOf( [&skip, &explainEntry](OneOf) noexcept { skip = true; explainEntry.Skipped("Skipped due to condition Eq|Set|AllSet with composite index."sv); diff --git a/cpp_src/core/nsselecter/querypreprocessor.h b/cpp_src/core/nsselecter/querypreprocessor.h index ba79d4c10..7248bdd80 100644 --- a/cpp_src/core/nsselecter/querypreprocessor.h +++ b/cpp_src/core/nsselecter/querypreprocessor.h @@ -1,7 +1,6 @@ #pragma once #include "aggregator.h" -#include "core/ft/ftsetcashe.h" #include "core/index/ft_preselect.h" #include "core/query/queryentry.h" #include "estl/h_vector.h" @@ -47,7 +46,7 @@ class QueryPreprocessor : private QueryEntries { unsigned Count() const noexcept { return count_; } bool MoreThanOneEvaluation() const noexcept { return queryEntryAddedByForcedSortOptimization_; } bool AvailableSelectBySortIndex() const noexcept { return !queryEntryAddedByForcedSortOptimization_ || !forcedStage(); } - void InjectConditionsFromJoins(JoinedSelectors &js, OnConditionInjections &expalainOnInjections, const RdxContext &rdxCtx); + void InjectConditionsFromJoins(JoinedSelectors &js, OnConditionInjections &expalainOnInjections, LogLevel, const RdxContext &rdxCtx); void Reduce(bool isFt); void InitIndexNumbers(); using QueryEntries::Size; diff --git a/cpp_src/core/nsselecter/selectiteratorcontainer.cc b/cpp_src/core/nsselecter/selectiteratorcontainer.cc index f34f73137..dfa14114e 100644 --- a/cpp_src/core/nsselecter/selectiteratorcontainer.cc +++ b/cpp_src/core/nsselecter/selectiteratorcontainer.cc @@ -70,9 +70,10 @@ bool SelectIteratorContainer::markBracketsHavingJoins(iterator begin, iterator e bool result = false; for (iterator it = begin; it != end; ++it) { result = it->InvokeAppropriate( - [it](SelectIteratorsBracket &b) { return (b.haveJoins = markBracketsHavingJoins(it.begin(), it.end())); }, - [](SelectIterator &) { return false; }, [](JoinSelectIterator &) { return true; }, - [](FieldsComparator &) { return false; }, [](AlwaysFalse &) { return false; }) || + [it](SelectIteratorsBracket &b) noexcept { return (b.haveJoins = markBracketsHavingJoins(it.begin(), it.end())); }, + [](SelectIterator &) noexcept { return false; }, [](JoinSelectIterator &) noexcept { return true; }, + [](FieldsComparator &) noexcept { return false; }, [](AlwaysFalse &) noexcept { return false; }, + [](AlwaysTrue &) noexcept { return false; }) || result; } return result; @@ -80,9 +81,9 @@ bool SelectIteratorContainer::markBracketsHavingJoins(iterator begin, iterator e bool SelectIteratorContainer::haveJoins(size_t i) const noexcept { return container_[i].InvokeAppropriate( - [](const SelectIteratorsBracket &b) { return b.haveJoins; }, [](const SelectIterator &) { return false; }, - [](const FieldsComparator &) { return false; }, [](const JoinSelectIterator &) { return true; }, - [](const AlwaysFalse &) { return false; }); + [](const SelectIteratorsBracket &b) noexcept { return b.haveJoins; }, [](const SelectIterator &) noexcept { return false; }, + [](const FieldsComparator &) noexcept { return false; }, [](const JoinSelectIterator &) noexcept { return true; }, + [](const AlwaysFalse &) noexcept { return false; }, [](const AlwaysTrue &) noexcept { return true; }); } void SelectIteratorContainer::moveJoinsToTheBeginingOfORs(span indexes, unsigned from, unsigned to) { @@ -103,11 +104,15 @@ void SelectIteratorContainer::moveJoinsToTheBeginingOfORs(span indexes SetOperation(OpOr, indexes[firstNotJoin]); if (IsJoinIterator(indexes[cur])) { unsigned tmp = indexes[cur]; - for (unsigned i = cur; i > firstNotJoin; --i) indexes[i] = indexes[i - 1]; + for (unsigned i = cur; i > firstNotJoin; --i) { + indexes[i] = indexes[i - 1]; + } indexes[firstNotJoin] = tmp; } else { memcpy(&buffer[0], &indexes[cur], sizeof(unsigned) * curSize); - for (unsigned i = cur - 1; i >= firstNotJoin; --i) indexes[i + curSize] = indexes[i]; + for (unsigned i = cur + curSize - 1, e = firstNotJoin + curSize; i >= e; --i) { + indexes[i] = indexes[i - curSize]; + } memcpy(&indexes[firstNotJoin], &buffer[0], sizeof(unsigned) * curSize); } } @@ -119,9 +124,10 @@ void SelectIteratorContainer::moveJoinsToTheBeginingOfORs(span indexes double SelectIteratorContainer::cost(span indexes, unsigned cur, int expectedIterations) const { return container_[indexes[cur]].InvokeAppropriate( [&](const SelectIteratorsBracket &) { return cost(indexes, cur + 1, cur + Size(indexes[cur]), expectedIterations); }, - [expectedIterations](const SelectIterator &sit) { return sit.Cost(expectedIterations); }, - [](const JoinSelectIterator &jit) { return jit.Cost(); }, - [expectedIterations](const FieldsComparator &c) { return c.Cost(expectedIterations); }, [](const AlwaysFalse &) { return 1; }); + [expectedIterations](const SelectIterator &sit) noexcept { return sit.Cost(expectedIterations); }, + [](const JoinSelectIterator &jit) noexcept { return jit.Cost(); }, + [expectedIterations](const FieldsComparator &c) noexcept { return c.Cost(expectedIterations); }, + [](const AlwaysFalse &) noexcept { return 1.0; }, [expectedIterations](const AlwaysTrue &) noexcept { return expectedIterations; }); } double SelectIteratorContainer::cost(span indexes, unsigned from, unsigned to, int expectedIterations) const { @@ -144,7 +150,7 @@ double SelectIteratorContainer::fullCost(span indexes, unsigned cur, u } bool SelectIteratorContainer::isIdset(const_iterator it, const_iterator end) { - return it->operation == OpAnd && it->HoldsOrReferTo() && + return it->operation == OpAnd && it->Is() && it->Value().comparators_.empty() && // !it->Value().empty() && (++it == end || it->operation != OpOr); } @@ -176,10 +182,9 @@ void SelectIteratorContainer::CheckFirstQuery() { // Let iterators choose most effective algorithm void SelectIteratorContainer::SetExpectMaxIterations(int expectedIterations) { assertrx(!Empty()); - assertrx(HoldsOrReferTo(0)); + assertrx(Is(0)); for (Container::iterator it = container_.begin() + 1; it != container_.end(); ++it) { - if (it->HoldsOrReferTo()) { - if (it->IsRef()) it->SetValue(it->Value()); + if (it->Is()) { it->Value().SetExpectMaxIterations(expectedIterations); } } @@ -308,10 +313,7 @@ void SelectIteratorContainer::processQueryEntryResults(SelectKeyResults &selectR if (last == this->end()) { throw Error(errQueryExec, "OR operator in first condition or after left join"); } - if (last->HoldsOrReferTo() && !last->Value().distinct && last->operation != OpNot) { - if (last->IsRef()) { - last->SetValue(last->Value()); - } + if (last->Is() && !last->Value().distinct && last->operation != OpNot) { SelectIterator &it = last->Value(); if (!qe.IsFieldIndexed() || isIndexSparse) { it.Append(res); @@ -331,9 +333,6 @@ void SelectIteratorContainer::processQueryEntryResults(SelectKeyResults &selectR if (qe.IsFieldIndexed() && !isIndexSparse) { // last appended is always a SelectIterator const auto lastAppendedIt = lastAppendedOrClosed(); - if (lastAppendedIt->IsRef()) { - lastAppendedIt->SetValue(lastAppendedIt->Value()); - } SelectIterator &lastAppended = lastAppendedIt->Value(); lastAppended.Bind(ns.payloadType_, qe.IndexNo()); lastAppended.SetNotOperationFlag(op == OpNot); @@ -412,7 +411,8 @@ std::vector SelectIteratorContainer::pr for (size_t j = begin, next; j < end; j = next) { next = queries.Next(j); queries.InvokeAppropriate( - j, Skip{}, + j, Skip{}, [](const SubQueryEntry &) { assertrx_throw(0); }, + [](const SubQueryFieldEntry &) { assertrx_throw(0); }, [&](const QueryEntry &eq) { if (foundFields.find(eq.FieldName()) != foundFields.end()) { throw Error(errParams, "Equal position field '%s' found twice in enclosing bracket; equal position fields: [%s]", @@ -470,6 +470,14 @@ bool SelectIteratorContainer::prepareIteratorsForSelectLoop(QueryPreprocessor &q const OpType op = queries.GetOperation(i); containFT = queries.InvokeAppropriate( i, + [](const SubQueryEntry &) -> bool { + assertrx_throw(0); + abort(); + }, + [](const SubQueryFieldEntry &) -> bool { + assertrx_throw(0); + abort(); + }, [&](const QueryEntriesBracket &) { OpenBracket(op); const bool contFT = @@ -506,8 +514,8 @@ bool SelectIteratorContainer::prepareIteratorsForSelectLoop(QueryPreprocessor &q if (ctx_) { if (ctx_->inTransaction) { strictMode = StrictModeNone; - } else if (ctx_->query.strictMode != StrictModeNotSet) { - strictMode = ctx_->query.strictMode; + } else if (ctx_->query.GetStrictMode() != StrictModeNotSet) { + strictMode = ctx_->query.GetStrictMode(); } } selectResults = processQueryEntry(qe, ns, strictMode); @@ -545,6 +553,10 @@ bool SelectIteratorContainer::prepareIteratorsForSelectLoop(QueryPreprocessor &q [this, op](const AlwaysFalse &) { Append(op, AlwaysFalse{}); return false; + }, + [this, op](const AlwaysTrue &) { + Append(op, AlwaysTrue{}); + return false; }) || containFT; } @@ -586,10 +598,11 @@ bool SelectIteratorContainer::checkIfSatisfyAllConditions(iterator begin, iterat // suggest that all JOINs in chain of OR ... OR ... OR ... OR will be before all not JOINs (see SortByCost) if (result) { // check what it does not holds join - if (it->InvokeAppropriate([](const SelectIteratorsBracket &b) { return !b.haveJoins; }, - [](const SelectIterator &) { return true; }, - [](const JoinSelectIterator &) { return false; }, - [](const FieldsComparator &) { return true; }, [](const AlwaysFalse &) { return true; })) + if (it->InvokeAppropriate( + [](const SelectIteratorsBracket &b) noexcept { return !b.haveJoins; }, + [](const SelectIterator &) noexcept { return true; }, [](const JoinSelectIterator &) noexcept { return false; }, + [](const FieldsComparator &) noexcept { return true; }, [](const AlwaysFalse &) noexcept { return true; }, + [](const AlwaysTrue &) noexcept { return true; })) continue; } } else { @@ -603,7 +616,8 @@ bool SelectIteratorContainer::checkIfSatisfyAllConditions(iterator begin, iterat }, [&](SelectIterator &sit) { return checkIfSatisfyCondition(sit, pv, &lastFinish, rowId, properRowId); }, [&](JoinSelectIterator &jit) { return checkIfSatisfyCondition(jit, pv, properRowId, match); }, - [&pv](FieldsComparator &c) { return c.Compare(pv); }, [](AlwaysFalse &) { return false; }); + [&pv](FieldsComparator &c) { return c.Compare(pv); }, [](AlwaysFalse &) noexcept { return false; }, + [](AlwaysTrue &) noexcept { return true; }); if (it->operation == OpOr) { result |= lastResult; currentFinish &= (!result && lastFinish); @@ -634,8 +648,9 @@ IdType SelectIteratorContainer::next(const_iterator it, IdType from) { } return from; }, - [from](const JoinSelectIterator &) { return from; }, [from](const FieldsComparator &) { return from; }, - [](const AlwaysFalse &) { + [from](const JoinSelectIterator &) noexcept { return from; }, [from](const FieldsComparator &) noexcept { return from; }, + [from](const AlwaysTrue &) noexcept { return from; }, + [](const AlwaysFalse &) noexcept { if constexpr (reverse) { return std::numeric_limits::lowest(); } else { @@ -709,7 +724,8 @@ void SelectIteratorContainer::dump(size_t level, const_iterator begin, const_ite }, [&ser](const SelectIterator &sit) { ser << sit.Dump(); }, [&ser, &joinedSelectors](const JoinSelectIterator &jit) { jit.Dump(ser, joinedSelectors); }, - [&ser](const FieldsComparator &c) { ser << c.Dump(); }, [&ser](const AlwaysFalse &) { ser << "Always False"; }); + [&ser](const FieldsComparator &c) { ser << c.Dump(); }, [&ser](const AlwaysFalse &) { ser << "Always False"; }, + [&ser](const AlwaysTrue &) { ser << "Always True"; }); ser << '\n'; } } diff --git a/cpp_src/core/nsselecter/selectiteratorcontainer.h b/cpp_src/core/nsselecter/selectiteratorcontainer.h index eb976796d..4f78afc6f 100644 --- a/cpp_src/core/nsselecter/selectiteratorcontainer.h +++ b/cpp_src/core/nsselecter/selectiteratorcontainer.h @@ -28,9 +28,10 @@ struct SelectIteratorsBracket : private Bracket { bool haveJoins = false; }; -class SelectIteratorContainer - : public ExpressionTree { - using Base = ExpressionTree; +class SelectIteratorContainer : public ExpressionTree { + using Base = + ExpressionTree; public: SelectIteratorContainer(PayloadType pt = PayloadType(), SelectCtx *ctx = nullptr) @@ -49,11 +50,11 @@ class SelectIteratorContainer bool IsSelectIterator(size_t i) const noexcept { assertrx(i < Size()); - return container_[i].HoldsOrReferTo(); + return container_[i].Is(); } bool IsJoinIterator(size_t i) const noexcept { assertrx(i < container_.size()); - return container_[i].HoldsOrReferTo(); + return container_[i].Is(); } void ExplainJSON(int iters, JsonBuilder &builder, const std::vector *js) const { explainJSON(cbegin(), cend(), iters, builder, js); diff --git a/cpp_src/core/nsselecter/sortexpression.cc b/cpp_src/core/nsselecter/sortexpression.cc index 6f5c0098a..fb52973d1 100644 --- a/cpp_src/core/nsselecter/sortexpression.cc +++ b/cpp_src/core/nsselecter/sortexpression.cc @@ -76,12 +76,12 @@ VariantArray SortExpression::GetJoinedFieldValues(IdType rowId, const joins::Nam bool SortExpression::ByIndexField() const noexcept { static constexpr SortExpressionOperation noOperation; - return Size() == 1 && container_[0].HoldsOrReferTo() && GetOperation(0) == noOperation; + return Size() == 1 && container_[0].Is() && GetOperation(0) == noOperation; } bool SortExpression::ByJoinedIndexField() const noexcept { static constexpr SortExpressionOperation noOperation; - return Size() == 1 && container_[0].HoldsOrReferTo() && GetOperation(0) == noOperation; + return Size() == 1 && container_[0].Is() && GetOperation(0) == noOperation; } const SortExprFuncs::JoinedIndex& SortExpression::GetJoinedIndex() const noexcept { diff --git a/cpp_src/core/payload/payloadiface.cc b/cpp_src/core/payload/payloadiface.cc index 64b50daec..9c6a0fa02 100644 --- a/cpp_src/core/payload/payloadiface.cc +++ b/cpp_src/core/payload/payloadiface.cc @@ -190,9 +190,8 @@ void PayloadIface::Set(int field, int idx, const Variant &v) { pv.Set(v); } -template -// template ::value>::type *> -int PayloadIface::ResizeArray(int field, int count, bool append) { +template <> +int PayloadIface::ResizeArray(int field, int count, bool append) { assertrx(t_.Field(field).IsArray()); size_t realSize = RealSize(); @@ -209,7 +208,7 @@ int PayloadIface::ResizeArray(int field, int count, bool append) { assertrx(insert <= realSize); - const_cast(v_)->Resize(realSize, realSize + grow - strip); + v_->Resize(realSize, realSize + grow - strip); memmove(v_->Ptr() + insert + grow - strip, v_->Ptr() + insert, realSize - insert); arr = reinterpret_cast(Field(field).p_); diff --git a/cpp_src/core/payload/payloadiface.h b/cpp_src/core/payload/payloadiface.h index 1781e1ce9..b95f6a791 100644 --- a/cpp_src/core/payload/payloadiface.h +++ b/cpp_src/core/payload/payloadiface.h @@ -181,6 +181,11 @@ class PayloadIface { T *v_; }; +template <> +int PayloadIface::ResizeArray(int, int, bool); +template <> +int PayloadIface::ResizeArray(int, int, bool) = delete; + template <> void PayloadIface::GetJSON(const TagsMatcher &, WrSerializer &); template <> diff --git a/cpp_src/core/query/dsl/dslencoder.cc b/cpp_src/core/query/dsl/dslencoder.cc index b8e92f6e3..f7f8a88a4 100644 --- a/cpp_src/core/query/dsl/dslencoder.cc +++ b/cpp_src/core/query/dsl/dslencoder.cc @@ -2,11 +2,11 @@ #include #include "core/cjson/jsonbuilder.h" -#include "core/keyvalue/key_string.h" #include "core/keyvalue/p_string.h" #include "core/query/query.h" #include "core/queryresults/aggregationresult.h" #include "dslparser.h" +#include "tools/logger.h" struct EnumClassHash { template @@ -50,7 +50,7 @@ void encodeSorting(const SortingEntries& sortingEntries, JsonBuilder& builder) { void encodeSingleJoinQuery(const JoinedQuery& joinQuery, JsonBuilder& builder); void encodeJoins(const Query& query, JsonBuilder& builder) { - for (const auto& joinQuery : query.joinQueries_) { + for (const auto& joinQuery : query.GetJoinQueries()) { if (joinQuery.joinType == LeftJoin) { auto node = builder.Object(); encodeSingleJoinQuery(joinQuery, node); @@ -71,9 +71,9 @@ void encodeEqualPositions(const EqualPositions_t& equalPositions, JsonBuilder& b void encodeFilters(const Query& query, JsonBuilder& builder) { auto arrNode = builder.Array("filters"); - query.entries.ToDsl(query, arrNode); + query.Entries().ToDsl(query, arrNode); encodeJoins(query, arrNode); - encodeEqualPositions(query.entries.equalPositions, arrNode); + encodeEqualPositions(query.Entries().equalPositions, arrNode); } void toDsl(const Query& query, JsonBuilder& builder); @@ -81,7 +81,7 @@ void toDsl(const Query& query, JsonBuilder& builder); void encodeMergedQueries(const Query& query, JsonBuilder& builder) { auto arrNode = builder.Array("merge_queries"); - for (const Query& mq : query.mergeQueries_) { + for (const Query& mq : query.GetMergeQueries()) { auto node = arrNode.Object(); toDsl(mq, node); } @@ -89,7 +89,7 @@ void encodeMergedQueries(const Query& query, JsonBuilder& builder) { void encodeSelectFilter(const Query& query, JsonBuilder& builder) { auto arrNode = builder.Array("select_filter"); - for (auto& str : query.selectFilter_) arrNode.Put(nullptr, str); + for (auto& str : query.SelectFilters()) arrNode.Put(nullptr, str); } void encodeSelectFunctions(const Query& query, JsonBuilder& builder) { @@ -141,27 +141,31 @@ void encodeSingleJoinQuery(const JoinedQuery& joinQuery, JsonBuilder& builder) { arr1.End(); // Close array auto selectFilters = node.Array("select_filter"); - for (const auto& str : joinQuery.selectFilter_) { + for (const auto& str : joinQuery.SelectFilters()) { selectFilters.Put(nullptr, str); } } -void encodeFilter(const QueryEntry& qentry, JsonBuilder& builder) { - if (qentry.Distinct()) return; - builder.Put("cond", get(cond_map, CondType(qentry.Condition()))); - builder.Put("field", qentry.FieldName()); - - if (qentry.Values().empty()) return; - if (qentry.Values().size() > 1 || qentry.Values()[0].Type().Is()) { +void putValues(JsonBuilder& builder, const VariantArray& values) { + if (values.empty()) { + return; + } else if (values.size() > 1 || values[0].Type().Is()) { auto arrNode = builder.Array("value"); - for (const Variant& kv : qentry.Values()) { + for (const Variant& kv : values) { arrNode.Put(nullptr, kv); } } else { - builder.Put("value", qentry.Values()[0]); + builder.Put("value", values[0]); } } +void encodeFilter(const QueryEntry& qentry, JsonBuilder& builder) { + if (qentry.Distinct()) return; + builder.Put("cond", get(cond_map, CondType(qentry.Condition()))); + builder.Put("field", qentry.FieldName()); + putValues(builder, qentry.Values()); +} + void encodeDropFields(const Query& query, JsonBuilder& builder) { auto dropFields = builder.Array("drop_fields"); for (const UpdateEntry& updateEntry : query.UpdateFields()) { @@ -205,9 +209,9 @@ void toDsl(const Query& query, JsonBuilder& builder) { builder.Put("limit", query.Limit()); builder.Put("offset", query.Offset()); builder.Put("req_total", get(reqtotal_values, query.CalcTotal())); - builder.Put("explain", query.explain_); + builder.Put("explain", query.GetExplain()); builder.Put("type", "select"); - auto strictMode = strictModeToString(query.strictMode); + auto strictMode = strictModeToString(query.GetStrictMode()); if (!strictMode.empty()) { builder.Put("strict_mode", strictMode); } @@ -223,7 +227,7 @@ void toDsl(const Query& query, JsonBuilder& builder) { } case QueryType::QueryUpdate: { builder.Put("namespace", query.NsName()); - builder.Put("explain", query.explain_); + builder.Put("explain", query.GetExplain()); builder.Put("type", "update"); encodeFilters(query, builder); bool withDropEntries = false, withUpdateEntries = false; @@ -245,7 +249,7 @@ void toDsl(const Query& query, JsonBuilder& builder) { } case QueryType::QueryDelete: { builder.Put("namespace", query.NsName()); - builder.Put("explain", query.explain_); + builder.Put("explain", query.GetExplain()); builder.Put("type", "delete"); encodeFilters(query, builder); break; @@ -276,7 +280,28 @@ void QueryEntries::toDsl(const_iterator it, const_iterator to, const Query& pare auto node = builder.Object(); node.Put("op", dsl::get(dsl::op_map, it->operation)); it->InvokeAppropriate( - Skip{}, + [&node](const AlwaysFalse&) { + logPrintf(LogTrace, "Not normalized query to dsl"); + node.Put("always", false); + }, + [&node](const AlwaysTrue&) { + logPrintf(LogTrace, "Not normalized query to dsl"); + node.Put("always", true); + }, + [&node, &parentQuery](const SubQueryEntry& sqe) { + node.Put("cond", dsl::get(dsl::cond_map, CondType(sqe.Condition()))); + { + auto subquery = node.Object("subquery"); + dsl::toDsl(parentQuery.GetSubQuery(sqe.QueryIndex()), subquery); + } + dsl::putValues(node, sqe.Values()); + }, + [&node, &parentQuery](const SubQueryFieldEntry& sqe) { + node.Put("cond", dsl::get(dsl::cond_map, CondType(sqe.Condition()))); + node.Put("field", sqe.FieldName()); + auto subquery = node.Object("subquery"); + dsl::toDsl(parentQuery.GetSubQuery(sqe.QueryIndex()), subquery); + }, [&it, &node, &parentQuery](const QueryEntriesBracket& bracket) { auto arrNode = node.Array("filters"); toDsl(it.cbegin(), it.cend(), parentQuery, arrNode); @@ -287,8 +312,8 @@ void QueryEntries::toDsl(const_iterator it, const_iterator to, const Query& pare dsl::encodeFilter(qe, node); }, [&node, &parentQuery](const JoinQueryEntry& jqe) { - assertrx(jqe.joinIndex < parentQuery.joinQueries_.size()); - dsl::encodeSingleJoinQuery(parentQuery.joinQueries_[jqe.joinIndex], node); + assertrx(jqe.joinIndex < parentQuery.GetJoinQueries().size()); + dsl::encodeSingleJoinQuery(parentQuery.GetJoinQueries()[jqe.joinIndex], node); }, [&node](const BetweenFieldsQueryEntry& qe) { node.Put("cond", dsl::get(dsl::cond_map, CondType(qe.Condition()))); diff --git a/cpp_src/core/query/dsl/dslparser.cc b/cpp_src/core/query/dsl/dslparser.cc index 13bac0c61..fd28e58fd 100644 --- a/cpp_src/core/query/dsl/dslparser.cc +++ b/cpp_src/core/query/dsl/dslparser.cc @@ -37,7 +37,7 @@ enum class Root { enum class Sort { Desc, Field, Values }; enum class JoinRoot { Type, On, Namespace, Filters, Sort, Limit, Offset, SelectFilter }; enum class JoinEntry { LeftField, RightField, Cond, Op }; -enum class Filter { Cond, Op, Field, Value, Filters, JoinQuery, FirstField, SecondField, EqualPositions }; +enum class Filter { Cond, Op, Field, Value, Filters, JoinQuery, FirstField, SecondField, EqualPositions, SubQuery, Always }; enum class Aggregation { Fields, Type, Sort, Limit, Offset }; enum class EqualPosition { Positions }; enum class UpdateField { Name, Type, Values, IsArray }; @@ -93,7 +93,9 @@ static const fast_str_map filter_map = {{"cond", Filter::Cond}, {"join_query", Filter::JoinQuery}, {"first_field", Filter::FirstField}, {"second_field", Filter::SecondField}, - {"equal_positions", Filter::EqualPositions}}; + {"equal_positions", Filter::EqualPositions}, + {"subquery", Filter::SubQuery}, + {"always", Filter::Always}}; // additional for 'filter::cond' field @@ -259,8 +261,10 @@ static void parseFilter(const JsonValue& filter, Query& q, std::vector subquery; + bool always{}; checkJsonValueType(filter, "filter", JSON_OBJECT); - enum { ENTRY, BRACKET, TWO_FIELDS_ENTRY, JOIN, EQUAL_POSITIONS } entryType = ENTRY; + enum { ENTRY, BRACKET, TWO_FIELDS_ENTRY, JOIN, EQUAL_POSITIONS, SUB_QUERY, ALWAYS } entryType = ENTRY; int elemsParsed = 0; for (const auto& elem : filter) { auto& v = elem.value; @@ -305,10 +309,10 @@ static void parseFilter(const JsonValue& filter, Query& q, std::vector(); + parse(v, *subquery); + entryType = SUB_QUERY; + break; + case Filter::Always: + if (v.getTag() == JSON_TRUE) { + always = true; + } else if (v.getTag() == JSON_FALSE) { + always = false; + } else { + throw Error{errParseDSL, "Wrong DSL format: 'always' fields in filter should be boolean"}; + } + entryType = ALWAYS; + break; } ++elemsParsed; } @@ -323,24 +342,41 @@ static void parseFilter(const JsonValue& filter, Query& q, std::vector 0); - const auto& qjoin = q.joinQueries_.back(); + assertrx(q.GetJoinQueries().size() > 0); + const auto& qjoin = q.GetJoinQueries().back(); if (qjoin.joinType != JoinType::LeftJoin) { - q.entries.Append((qjoin.joinType == JoinType::InnerJoin) ? OpAnd : OpOr, JoinQueryEntry(q.joinQueries_.size() - 1)); + q.AppendQueryEntry((qjoin.joinType == JoinType::InnerJoin) ? OpAnd : OpOr, q.GetJoinQueries().size() - 1); } break; } case EQUAL_POSITIONS: break; + case SUB_QUERY: + q.NextOp(op); + if (fields[0].empty()) { + q.Where(std::move(*subquery), condition, std::move(values)); + } else if (values.empty()) { + q.Where(std::move(fields[0]), condition, std::move(*subquery)); + } else { + throw Error{errParseDSL, "Wrong DSL format: 'value', 'subquery' and 'field' fields in one filter"}; + } + break; + case ALWAYS: + if (always) { + q.AppendQueryEntry(op); + } else { + q.AppendQueryEntry(op); + } + break; } } @@ -417,19 +453,21 @@ void parseSingleJoinQuery(const JsonValue& join, Query& query) { if (!qjoin.CanAddSelectFilter()) { throw Error(errConflict, kAggregationWithSelectFieldsMsgError); } - parseStringArray(value, qjoin.selectFilter_); + std::vector selectFilters; + parseStringArray(value, selectFilters); + qjoin.Select(std::move(selectFilters)); break; } } } for (auto&& eqPos : equalPositions) { if (eqPos.first == 0) { - qjoin.entries.equalPositions.emplace_back(std::move(eqPos.second)); + qjoin.SetEqualPositions(std::move(eqPos.second)); } else { - qjoin.entries.Get(eqPos.first - 1).equalPositions.emplace_back(std::move(eqPos.second)); + qjoin.SetEqualPositions(eqPos.first - 1, std::move(eqPos.second)); } } - query.joinQueries_.emplace_back(std::move(qjoin)); + query.AddJoinQuery(std::move(qjoin)); } static void parseMergeQueries(const JsonValue& mergeQueries, Query& query) { @@ -439,7 +477,7 @@ static void parseMergeQueries(const JsonValue& mergeQueries, Query& query) { JoinedQuery qmerged; parse(merged, qmerged); qmerged.joinType = Merge; - query.mergeQueries_.emplace_back(std::move(qmerged)); + query.Merge(std::move(qmerged)); } } @@ -607,7 +645,9 @@ void parse(const JsonValue& root, Query& q) { throw Error(errConflict, kAggregationWithSelectFieldsMsgError); } checkJsonValueType(v, name, JSON_ARRAY); - parseStringArray(v, q.selectFilter_); + std::vector selectFilters; + parseStringArray(v, selectFilters); + q.Select(std::move(selectFilters)); break; } case Root::SelectFunctions: @@ -624,7 +664,7 @@ void parse(const JsonValue& root, Query& q) { break; case Root::Explain: checkJsonValueType(v, name, JSON_FALSE, JSON_TRUE); - q.explain_ = v.getTag() == JSON_TRUE; + q.Explain(v.getTag() == JSON_TRUE); break; case Root::WithRank: checkJsonValueType(v, name, JSON_FALSE, JSON_TRUE); @@ -632,8 +672,8 @@ void parse(const JsonValue& root, Query& q) { break; case Root::StrictMode: checkJsonValueType(v, name, JSON_STRING); - q.strictMode = strictModeFromString(std::string(v.toString())); - if (q.strictMode == StrictModeNotSet) { + q.Strict(strictModeFromString(std::string(v.toString()))); + if (q.GetStrictMode() == StrictModeNotSet) { throw Error(errParseDSL, "Unexpected strict mode value: %s", v.toString()); } break; @@ -659,20 +699,20 @@ void parse(const JsonValue& root, Query& q) { } for (auto&& eqPos : equalPositions) { if (eqPos.first == 0) { - q.entries.equalPositions.emplace_back(std::move(eqPos.second)); + q.SetEqualPositions(std::move(eqPos.second)); } else { - q.entries.Get(eqPos.first - 1).equalPositions.emplace_back(std::move(eqPos.second)); + q.SetEqualPositions(eqPos.first - 1, std::move(eqPos.second)); } } } #include "query.json.h" -Error Parse(const std::string& str, Query& q) { +Error Parse(std::string_view str, Query& q) { static JsonSchemaChecker schemaChecker(kQueryJson, "query"); try { gason::JsonParser parser; - auto root = parser.Parse(std::string_view(str)); + auto root = parser.Parse(str); Error err = schemaChecker.Check(root); if (!err.ok()) return err; dsl::parse(root.value, q); diff --git a/cpp_src/core/query/dsl/dslparser.h b/cpp_src/core/query/dsl/dslparser.h index d9d6afd00..ef8df2bbf 100644 --- a/cpp_src/core/query/dsl/dslparser.h +++ b/cpp_src/core/query/dsl/dslparser.h @@ -1,12 +1,15 @@ #pragma once -#include -#include "core/type_consts.h" +#include #include "tools/errors.h" namespace reindexer { + class Query; + namespace dsl { -Error Parse(const std::string& dsl, Query& q); + +[[nodiscard]] Error Parse(std::string_view dsl, Query& q); + } // namespace dsl } // namespace reindexer diff --git a/cpp_src/core/query/dsl/query.json.h b/cpp_src/core/query/dsl/query.json.h index 4aa753618..6304715b1 100644 --- a/cpp_src/core/query/dsl/query.json.h +++ b/cpp_src/core/query/dsl/query.json.h @@ -1 +1 @@ -inline const std::string kQueryJson = {0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x66,0x69,0x6e,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x51,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x46,0x69,0x6c,0x74,0x65,0x72,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x53,0x6f,0x72,0x74,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x4f,0x6e,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x4a,0x6f,0x69,0x6e,0x65,0x64,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x45,0x71,0x75,0x61,0x6c,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x55,0x70,0x64,0x61,0x74,0x65,0x46,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x41,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x53,0x6f,0x72,0x74,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x41,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,}; \ No newline at end of file +inline const std::string kQueryJson = {0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x66,0x69,0x6e,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x51,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x46,0x69,0x6c,0x74,0x65,0x72,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x53,0x6f,0x72,0x74,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x4f,0x6e,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x4a,0x6f,0x69,0x6e,0x65,0x64,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6a,0x6f,0x69,0x6e,0x5f,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x66,0x69,0x72,0x73,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x63,0x6f,0x6e,0x64,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x75,0x62,0x71,0x75,0x65,0x72,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x72,0x65,0x71,0x5f,0x74,0x6f,0x74,0x61,0x6c,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x66,0x69,0x6c,0x74,0x65,0x72,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6d,0x65,0x72,0x67,0x65,0x5f,0x71,0x75,0x65,0x72,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x72,0x6f,0x70,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x75,0x70,0x64,0x61,0x74,0x65,0x5f,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x77,0x69,0x74,0x68,0x5f,0x72,0x61,0x6e,0x6b,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x73,0x74,0x72,0x69,0x63,0x74,0x5f,0x6d,0x6f,0x64,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x61,0x6c,0x77,0x61,0x79,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x65,0x71,0x75,0x61,0x6c,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x6e,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6c,0x65,0x66,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x72,0x69,0x67,0x68,0x74,0x5f,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x63,0x6f,0x6e,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x70,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x73,0x65,0x6c,0x65,0x63,0x74,0x5f,0x66,0x69,0x6c,0x74,0x65,0x72,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x55,0x70,0x64,0x61,0x74,0x65,0x46,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x22,0x2c,0x20,0x22,0x69,0x73,0x5f,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x6e,0x61,0x6d,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x69,0x73,0x5f,0x61,0x72,0x72,0x61,0x79,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x2c,0x20,0x22,0x76,0x61,0x6c,0x75,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x74,0x72,0x75,0x65,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x41,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x53,0x6f,0x72,0x74,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x41,0x67,0x67,0x72,0x65,0x67,0x61,0x74,0x69,0x6f,0x6e,0x73,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x2c,0x20,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x73,0x6f,0x72,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x64,0x22,0x3a,0x20,0x5b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x5d,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x66,0x69,0x65,0x6c,0x64,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x2c,0x20,0x22,0x64,0x65,0x73,0x63,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x22,0x7d,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x6c,0x69,0x6d,0x69,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x2c,0x20,0x22,0x6f,0x66,0x66,0x73,0x65,0x74,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,0x22,0x7d,0x7d,0x7d,0x2c,0x20,0x22,0x45,0x71,0x75,0x61,0x6c,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x44,0x65,0x66,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x6f,0x62,0x6a,0x65,0x63,0x74,0x22,0x2c,0x20,0x22,0x61,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x22,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x22,0x3a,0x20,0x7b,0x22,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x61,0x72,0x72,0x61,0x79,0x22,0x2c,0x20,0x22,0x69,0x74,0x65,0x6d,0x73,0x22,0x3a,0x20,0x7b,0x22,0x74,0x79,0x70,0x65,0x22,0x3a,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,}; \ No newline at end of file diff --git a/cpp_src/core/query/query.cc b/cpp_src/core/query/query.cc index 49b6f3dec..c8e5fe0fa 100644 --- a/cpp_src/core/query/query.cc +++ b/cpp_src/core/query/query.cc @@ -1,4 +1,3 @@ - #include "core/query/query.h" #include "core/query/dsl/dslencoder.h" #include "core/query/dsl/dslparser.h" @@ -13,28 +12,101 @@ using namespace std::string_view_literals; const std::string_view kLsnIndexName = "#lsn"sv; const std::string_view kSlaveVersionIndexName = "#slave_version"sv; +void Query::checkSubQuery() const { + if rx_unlikely (type_ != QuerySelect) { + throw Error{errQueryExec, "Subquery should be select"}; + } + if rx_unlikely (!joinQueries_.empty()) { + throw Error{errQueryExec, "Join cannot be in subquery"}; + } + if rx_unlikely (!mergeQueries_.empty()) { + throw Error{errQueryExec, "Merge cannot be in subquery"}; + } + if rx_unlikely (!subQueries_.empty()) { + throw Error{errQueryExec, "Subquery cannot be in subquery"}; + } + if rx_unlikely (!selectFunctions_.empty()) { + throw Error{errQueryExec, "Select function cannot be in subquery"}; + } + if rx_unlikely (!updateFields_.empty()) { + throw Error{errQueryExec, "Subquery cannot update"}; + } + if rx_unlikely (withRank_) { + throw Error{errQueryExec, "Subquery cannot request rank"}; + } + if rx_unlikely (isSystemNamespaceNameFast(NsName())) { + throw Error{errQueryExec, "Queries to system namespaces ('%s') are not supported inside subquery", NsName()}; + } + if rx_unlikely (IsWALQuery()) { + throw Error{errQueryExec, "WAL queries are not supported inside subquery"}; + } +} + +void Query::checkSubQueryNoData() const { + if rx_unlikely (!aggregations_.empty()) { + throw Error{errQueryExec, "Aggregaton cannot be in subquery with condition Any or Empty"}; + } + if rx_unlikely (HasLimit() && Limit() != 0) { + throw Error{errQueryExec, "Limit cannot be in subquery with condition Any or Empty"}; + } + if rx_unlikely (HasOffset()) { + throw Error{errQueryExec, "Offset cannot be in subquery with condition Any or Empty"}; + } + if rx_unlikely (calcTotal_ != ModeNoTotal) { + throw Error{errQueryExec, "Total request cannot be in subquery with condition Any or Empty"}; + } + if rx_unlikely (!selectFilter_.empty()) { + throw Error{errQueryExec, "Select fields filter cannot be in subquery with condition Any or Empty"}; + } + checkSubQuery(); +} + +void Query::checkSubQueryWithData() const { + if rx_unlikely ((aggregations_.size() + selectFilter_.size() + (calcTotal_ == ModeNoTotal ? 0 : 1)) != 1) { + throw Error{errQueryExec, "Subquery should contain exactly one of aggregation, select field filter or total request"}; + } + if (!aggregations_.empty()) { + switch (aggregations_[0].Type()) { + case AggDistinct: + case AggUnknown: + case AggFacet: + throw Error{errQueryExec, "Aggregation %s cannot be in subquery", AggTypeToStr(aggregations_[0].Type())}; + case AggMin: + case AggMax: + case AggAvg: + case AggSum: + case AggCount: + case AggCountCached: + break; + } + } + checkSubQuery(); +} + +void Query::VerifyForUpdate() const { + if (!subQueries_.empty()) { + throw Error{errQueryExec, "UPDATE and DELETE query cannot contain subqueries"}; + } + if (!joinQueries_.empty()) { + throw Error{errQueryExec, "UPDATE and DELETE query cannot contain join"}; + } +} + bool Query::operator==(const Query &obj) const { - if (entries != obj.entries) return false; - if (aggregations_ != obj.aggregations_) return false; - - if (NsName() != obj.NsName()) return false; - if (sortingEntries_ != obj.sortingEntries_) return false; - if (CalcTotal() != obj.CalcTotal()) return false; - if (Offset() != obj.Offset()) return false; - if (Limit() != obj.Limit()) return false; - if (debugLevel != obj.debugLevel) return false; - if (strictMode != obj.strictMode) return false; - if (forcedSortOrder_.size() != obj.forcedSortOrder_.size()) return false; + if (entries_ != obj.entries_ || aggregations_ != obj.aggregations_ || + + NsName() != obj.NsName() || sortingEntries_ != obj.sortingEntries_ || CalcTotal() != obj.CalcTotal() || Offset() != obj.Offset() || + Limit() != obj.Limit() || debugLevel_ != obj.debugLevel_ || strictMode_ != obj.strictMode_ || selectFilter_ != obj.selectFilter_ || + selectFunctions_ != obj.selectFunctions_ || joinQueries_ != obj.joinQueries_ || mergeQueries_ != obj.mergeQueries_ || + updateFields_ != obj.updateFields_ || subQueries_ != obj.subQueries_ || forcedSortOrder_.size() != obj.forcedSortOrder_.size()) { + return false; + } for (size_t i = 0, s = forcedSortOrder_.size(); i < s; ++i) { - if (forcedSortOrder_[i].RelaxCompare(obj.forcedSortOrder_[i]) != 0) return false; + if (forcedSortOrder_[i].RelaxCompare(obj.forcedSortOrder_[i]) != 0) { + return false; + } } - if (selectFilter_ != obj.selectFilter_) return false; - if (selectFunctions_ != obj.selectFunctions_) return false; - if (joinQueries_ != obj.joinQueries_) return false; - if (mergeQueries_ != obj.mergeQueries_) return false; - if (updateFields_ != obj.updateFields_) return false; - return true; } @@ -43,13 +115,16 @@ bool JoinedQuery::operator==(const JoinedQuery &obj) const { if (joinType != obj.joinType) return false; return Query::operator==(obj); } -void Query::FromSQL(std::string_view q) { SQLParser(*this).Parse(q); } +Query Query::FromSQL(std::string_view q) { return SQLParser::Parse(q); } -Error Query::FromJSON(const std::string &dsl) { return dsl::Parse(dsl, *this); } +Error Query::FromJSON(std::string_view dsl) { return dsl::Parse(dsl, *this); } std::string Query::GetJSON() const { return dsl::toDsl(*this); } WrSerializer &Query::GetSQL(WrSerializer &ser, bool stripArgs) const { return SQLEncoder(*this).GetSQL(ser, stripArgs); } +WrSerializer &Query::GetSQL(WrSerializer &ser, QueryType realType, bool stripArgs) const { + return SQLEncoder(*this, realType).GetSQL(ser, stripArgs); +} std::string Query::GetSQL(bool stripArgs) const { WrSerializer ser; @@ -61,34 +136,67 @@ std::string Query::GetSQL(QueryType realType) const { return std::string(SQLEncoder(*this, realType).GetSQL(ser, false).Slice()); } +void Query::Join(JoinedQuery &&jq) & { + switch (jq.joinType) { + case JoinType::Merge: + if (nextOp_ != OpAnd) { + throw Error(errParams, "Merge query with %s operation", OpTypeToStr(nextOp_)); + } + mergeQueries_.emplace_back(std::move(jq)); + return; + case JoinType::LeftJoin: + if (nextOp_ != OpAnd) { + throw Error(errParams, "Left join with %s operation", OpTypeToStr(nextOp_)); + } + break; + case JoinType::OrInnerJoin: + if (nextOp_ == OpNot) { + throw Error(errParams, "Or inner join with %s operation", OpTypeToStr(nextOp_)); + } + nextOp_ = OpOr; + [[fallthrough]]; + case JoinType::InnerJoin: + entries_.Append(nextOp_, JoinQueryEntry(joinQueries_.size())); + nextOp_ = OpAnd; + break; + } + joinQueries_.emplace_back(std::move(jq)); + adoptNested(joinQueries_.back()); +} + +VariantArray Query::deserializeValues(Serializer &ser, CondType cond) { + VariantArray values; + auto cnt = ser.GetVarUint(); + if (cond == CondDWithin) { + if (cnt != 3) { + throw Error(errParseBin, "Expected point and distance for DWithin"); + } + VariantArray point; + point.reserve(2); + point.emplace_back(ser.GetVariant().EnsureHold()); + point.emplace_back(ser.GetVariant().EnsureHold()); + values.reserve(2); + values.emplace_back(std::move(point)); + values.emplace_back(ser.GetVariant().EnsureHold()); + } else { + values.reserve(cnt); + while (cnt--) values.emplace_back(ser.GetVariant().EnsureHold()); + } + return values; +} + void Query::deserialize(Serializer &ser, bool &hasJoinConditions) { bool end = false; std::vector> equalPositions; while (!end && !ser.Eof()) { - int qtype = ser.GetVarUint(); + QueryItemType qtype = QueryItemType(ser.GetVarUint()); switch (qtype) { case QueryCondition: { const auto fieldName = ser.GetVString(); const OpType op = OpType(ser.GetVarUint()); const CondType condition = CondType(ser.GetVarUint()); - int cnt = ser.GetVarUint(); - VariantArray values; - if (condition == CondDWithin) { - if (cnt != 3) { - throw Error(errParseBin, "Expected point and distance for DWithin"); - } - VariantArray point; - point.reserve(2); - point.emplace_back(ser.GetVariant().EnsureHold()); - point.emplace_back(ser.GetVariant().EnsureHold()); - values.reserve(2); - values.emplace_back(std::move(point)); - values.emplace_back(ser.GetVariant().EnsureHold()); - } else { - values.reserve(cnt); - while (cnt--) values.emplace_back(ser.GetVariant().EnsureHold()); - } - entries.Append(op, std::string{fieldName}, condition, std::move(values)); + VariantArray values = deserializeValues(ser, condition); + entries_.Append(op, std::string{fieldName}, condition, std::move(values)); break; } case QueryBetweenFieldsCondition: { @@ -96,12 +204,17 @@ void Query::deserialize(Serializer &ser, bool &hasJoinConditions) { std::string firstField{ser.GetVString()}; CondType condition = static_cast(ser.GetVarUint()); std::string secondField{ser.GetVString()}; - entries.Append(op, std::move(firstField), condition, std::move(secondField)); + entries_.Append(op, std::move(firstField), condition, std::move(secondField)); break; } case QueryAlwaysFalseCondition: { const OpType op = OpType(ser.GetVarUint()); - entries.Append(op); + entries_.Append(op); + break; + } + case QueryAlwaysTrueCondition: { + const OpType op = OpType(ser.GetVarUint()); + entries_.Append(op); break; } case QueryJoinCondition: { @@ -110,7 +223,7 @@ void Query::deserialize(Serializer &ser, bool &hasJoinConditions) { JoinQueryEntry joinEntry(ser.GetVarUint()); hasJoinConditions = true; // NOLINTNEXTLINE(performance-move-const-arg) - entries.Append((type == JoinType::OrInnerJoin) ? OpOr : OpAnd, std::move(joinEntry)); + entries_.Append((type == JoinType::OrInnerJoin) ? OpOr : OpAnd, std::move(joinEntry)); break; } case QueryAggregation: { @@ -148,7 +261,7 @@ void Query::deserialize(Serializer &ser, bool &hasJoinConditions) { case QueryDistinct: { const auto fieldName = ser.GetVString(); if (!fieldName.empty()) { - entries.Append(OpAnd, std::string{fieldName}, QueryEntry::DistinctTag{}); + entries_.Append(OpAnd, std::string{fieldName}, QueryEntry::DistinctTag{}); } break; } @@ -177,10 +290,10 @@ void Query::deserialize(Serializer &ser, bool &hasJoinConditions) { break; } case QueryDebugLevel: - debugLevel = ser.GetVarUint(); + Debug(ser.GetVarUint()); break; case QueryStrictMode: - strictMode = StrictMode(ser.GetVarUint()); + strictMode_ = StrictMode(ser.GetVarUint()); break; case QueryLimit: count_ = ser.GetVarUint(); @@ -255,24 +368,45 @@ void Query::deserialize(Serializer &ser, bool &hasJoinConditions) { } case QueryOpenBracket: { OpType op = OpType(ser.GetVarUint()); - entries.OpenBracket(op); + entries_.OpenBracket(op); break; } case QueryCloseBracket: - entries.CloseBracket(); + entries_.CloseBracket(); break; case QueryEnd: end = true; break; + case QuerySubQueryCondition: { + OpType op = OpType(ser.GetVarUint()); + Serializer subQuery{ser.GetVString()}; + CondType condition = CondType(ser.GetVarUint()); + VariantArray values = deserializeValues(ser, condition); + NextOp(op); + Where(Query::Deserialize(subQuery), condition, std::move(values)); + break; + } + case QueryFieldSubQueryCondition: { + OpType op = OpType(ser.GetVarUint()); + const auto fieldName = ser.GetVString(); + CondType condition = CondType(ser.GetVarUint()); + Serializer subQuery{ser.GetVString()}; + NextOp(op); + Where(fieldName, condition, Query::Deserialize(subQuery)); + break; + } + case QueryAggregationSort: + case QueryAggregationOffset: + case QueryAggregationLimit: default: throw Error(errParseBin, "Unknown type %d while parsing binary buffer", qtype); } } for (auto &&eqPos : equalPositions) { if (eqPos.first == 0) { - entries.equalPositions.emplace_back(std::move(eqPos.second)); + entries_.equalPositions.emplace_back(std::move(eqPos.second)); } else { - entries.Get(eqPos.first - 1).equalPositions.emplace_back(std::move(eqPos.second)); + entries_.Get(eqPos.first - 1).equalPositions.emplace_back(std::move(eqPos.second)); } } return; @@ -280,7 +414,7 @@ void Query::deserialize(Serializer &ser, bool &hasJoinConditions) { void Query::Serialize(WrSerializer &ser, uint8_t mode) const { ser.PutVString(NsName()); - entries.Serialize(ser); + entries_.Serialize(ser, subQueries_); for (const auto &agg : aggregations_) { ser.PutVarUint(QueryAggregation); @@ -323,15 +457,15 @@ void Query::Serialize(WrSerializer &ser, uint8_t mode) const { } } - for (const auto &equalPoses : entries.equalPositions) { + for (const auto &equalPoses : entries_.equalPositions) { ser.PutVarUint(QueryEqualPosition); ser.PutVarUint(0); ser.PutVarUint(equalPoses.size()); for (const auto &ep : equalPoses) ser.PutVString(ep); } - for (size_t i = 0; i < entries.Size(); ++i) { - if (entries.IsSubTree(i)) { - const auto &bracket = entries.Get(i); + for (size_t i = 0; i < entries_.Size(); ++i) { + if (entries_.IsSubTree(i)) { + const auto &bracket = entries_.Get(i); for (const auto &equalPoses : bracket.equalPositions) { ser.PutVarUint(QueryEqualPosition); ser.PutVarUint(i + 1); @@ -342,11 +476,11 @@ void Query::Serialize(WrSerializer &ser, uint8_t mode) const { } ser.PutVarUint(QueryDebugLevel); - ser.PutVarUint(debugLevel); + ser.PutVarUint(debugLevel_); - if (strictMode != StrictModeNotSet) { + if (strictMode_ != StrictModeNotSet) { ser.PutVarUint(QueryStrictMode); - ser.PutVarUint(int(strictMode)); + ser.PutVarUint(int(strictMode_)); } if (!(mode & SkipLimitOffset)) { @@ -360,7 +494,7 @@ void Query::Serialize(WrSerializer &ser, uint8_t mode) const { } } - if (CalcTotal() != ModeNoTotal) { + if (HasCalcTotal()) { ser.PutVarUint(QueryReqTotal); ser.PutVarUint(CalcTotal()); } @@ -413,10 +547,10 @@ void Query::Serialize(WrSerializer &ser, uint8_t mode) const { } } -void Query::Deserialize(Serializer &ser) { - namespace_ = std::string(ser.GetVString()); +Query Query::Deserialize(Serializer &ser) { + Query res(ser.GetVString()); bool hasJoinConditions = false; - deserialize(ser, hasJoinConditions); + res.deserialize(ser, hasJoinConditions); bool nested = false; while (!ser.Eof()) { @@ -424,82 +558,54 @@ void Query::Deserialize(Serializer &ser) { JoinedQuery q1(std::string(ser.GetVString())); q1.joinType = joinType; q1.deserialize(ser, hasJoinConditions); - q1.debugLevel = debugLevel; - q1.strictMode = strictMode; + res.adoptNested(q1); if (joinType == JoinType::Merge) { - mergeQueries_.emplace_back(std::move(q1)); + res.mergeQueries_.emplace_back(std::move(q1)); nested = true; } else { - Query &q = nested ? mergeQueries_.back() : *this; + Query &q = nested ? res.mergeQueries_.back() : res; if (joinType != JoinType::LeftJoin && !hasJoinConditions) { - const size_t joinIdx = joinQueries_.size(); - entries.Append((joinType == JoinType::OrInnerJoin) ? OpOr : OpAnd, joinIdx); + const size_t joinIdx = res.joinQueries_.size(); + res.entries_.Append((joinType == JoinType::OrInnerJoin) ? OpOr : OpAnd, joinIdx); } q.joinQueries_.emplace_back(std::move(q1)); + q.adoptNested(q.joinQueries_.back()); } } + return res; } Query &Query::Join(JoinType joinType, std::string leftField, std::string rightField, CondType cond, OpType op, Query &&qr) & { - auto &jq = joinQueries_.emplace_back(joinType, std::move(qr)); + auto jq = JoinedQuery{joinType, std::move(qr)}; jq.joinEntries_.emplace_back(op, cond, std::move(leftField), std::move(rightField)); - if (joinType != JoinType::LeftJoin) { - entries.Append((joinType == JoinType::InnerJoin) ? OpType::OpAnd : OpType::OpOr, joinQueries_.size() - 1); - } + Join(std::move(jq)); return *this; } Query &Query::Join(JoinType joinType, std::string leftField, std::string rightField, CondType cond, OpType op, const Query &qr) & { - joinQueries_.emplace_back(joinType, qr); - joinQueries_.back().joinEntries_.emplace_back(op, cond, std::move(leftField), std::move(rightField)); - if (joinType != JoinType::LeftJoin) { - entries.Append((joinType == JoinType::InnerJoin) ? OpType::OpAnd : OpType::OpOr, joinQueries_.size() - 1); - } + auto jq = JoinedQuery{joinType, qr}; + jq.joinEntries_.emplace_back(op, cond, std::move(leftField), std::move(rightField)); + Join(std::move(jq)); return *this; } -Query::OnHelper Query::Join(JoinType joinType, Query &&q) & { - joinQueries_.emplace_back(joinType, std::move(q)); - if (joinType != JoinType::LeftJoin) { - entries.Append((joinType == JoinType::InnerJoin) ? OpType::OpAnd : OpType::OpOr, joinQueries_.size() - 1); - } - return {*this, joinQueries_.back()}; -} - -Query::OnHelper Query::Join(JoinType joinType, const Query &q) & { - joinQueries_.emplace_back(joinType, q); - if (joinType != JoinType::LeftJoin) { - entries.Append((joinType == JoinType::InnerJoin) ? OpType::OpAnd : OpType::OpOr, joinQueries_.size() - 1); - } - return {*this, joinQueries_.back()}; -} - -Query::OnHelperR Query::Join(JoinType joinType, Query &&q) && { - joinQueries_.emplace_back(joinType, std::move(q)); - if (joinType != JoinType::LeftJoin) { - entries.Append((joinType == JoinType::InnerJoin) ? OpType::OpAnd : OpType::OpOr, joinQueries_.size() - 1); - } - return {std::move(*this), joinQueries_.back()}; -} - -Query::OnHelperR Query::Join(JoinType joinType, const Query &q) && { - joinQueries_.emplace_back(joinType, q); - if (joinType != JoinType::LeftJoin) { - entries.Append((joinType == JoinType::InnerJoin) ? OpType::OpAnd : OpType::OpOr, joinQueries_.size() - 1); - } - return {std::move(*this), joinQueries_.back()}; -} - Query &Query::Merge(const Query &q) & { mergeQueries_.emplace_back(JoinType::Merge, q); + adoptNested(mergeQueries_.back()); return *this; } Query &Query::Merge(Query &&q) & { mergeQueries_.emplace_back(JoinType::Merge, std::move(q)); + adoptNested(mergeQueries_.back()); return *this; } +void Query::AddJoinQuery(JoinedQuery &&jq) { + adoptNested(jq); + joinQueries_.emplace_back(std::move(jq)); +} + Query &Query::SortStDistance(std::string_view field, Point p, bool desc) & { if (field.empty()) { throw Error(errParams, "Field name for ST_Distance can not be empty"); @@ -516,21 +622,60 @@ Query &Query::SortStDistance(std::string_view field1, std::string_view field2, b return *this; } -void Query::WalkNested(bool withSelf, bool withMerged, const std::function &visitor) const { +void Query::walkNested(bool withSelf, bool withMerged, bool withSubQueries, + const std::function &visitor) noexcept(noexcept(visitor(std::declval()))) { if (withSelf) visitor(*this); - if (withMerged) + if (withMerged) { for (auto &mq : mergeQueries_) visitor(mq); + if (withSubQueries) { + for (auto &mq : mergeQueries_) { + for (auto &nq : mq.subQueries_) { + nq.walkNested(true, true, true, visitor); + } + } + } + } for (auto &jq : joinQueries_) visitor(jq); - for (auto &mq : mergeQueries_) + for (auto &mq : mergeQueries_) { for (auto &jq : mq.joinQueries_) visitor(jq); + } + if (withSubQueries) { + for (auto &nq : subQueries_) { + nq.walkNested(true, withMerged, true, visitor); + } + } +} + +void Query::WalkNested(bool withSelf, bool withMerged, bool withSubQueries, const std::function &visitor) const + noexcept(noexcept(visitor(std::declval()))) { + if (withSelf) visitor(*this); + if (withMerged) { + for (auto &mq : mergeQueries_) visitor(mq); + if (withSubQueries) { + for (auto &mq : mergeQueries_) { + for (auto &nq : mq.subQueries_) { + nq.WalkNested(true, true, true, visitor); + } + } + } + } + for (auto &jq : joinQueries_) visitor(jq); + for (auto &mq : mergeQueries_) { + for (auto &jq : mq.joinQueries_) visitor(jq); + } + if (withSubQueries) { + for (auto &nq : subQueries_) { + nq.WalkNested(true, withMerged, true, visitor); + } + } } bool Query::IsWALQuery() const noexcept { - if (entries.Size() == 1 && entries.HoldsOrReferTo(0) && kLsnIndexName == entries.Get(0).FieldName()) { + if (entries_.Size() == 1 && entries_.Is(0) && kLsnIndexName == entries_.Get(0).FieldName()) { return true; - } else if (entries.Size() == 2 && entries.HoldsOrReferTo(0) && entries.HoldsOrReferTo(1)) { - const auto &index0 = entries.Get(0).FieldName(); - const auto &index1 = entries.Get(1).FieldName(); + } else if (entries_.Size() == 2 && entries_.Is(0) && entries_.Is(1)) { + const auto &index0 = entries_.Get(0).FieldName(); + const auto &index1 = entries_.Get(1).FieldName(); return (kLsnIndexName == index0 && kSlaveVersionIndexName == index1) || (kLsnIndexName == index1 && kSlaveVersionIndexName == index0); } diff --git a/cpp_src/core/query/query.h b/cpp_src/core/query/query.h index 355cd805d..bad029f06 100644 --- a/cpp_src/core/query/query.h +++ b/cpp_src/core/query/query.h @@ -22,113 +22,76 @@ constexpr std::string_view kAggregationWithSelectFieldsMsgError = /// Allows to select data from DB. /// Analog to ansi-sql select query. class Query { - template - class OnHelperTempl; - template - class OnHelperGroup { - public: - OnHelperGroup &&Not() &&noexcept { - op_ = OpNot; - return std::move(*this); - } - OnHelperGroup &&Or() &&noexcept { - op_ = OpOr; - return std::move(*this); - } - OnHelperGroup &&On(std::string index, CondType cond, std::string joinIndex) &&; - Q CloseBracket() &&noexcept { return std::forward(q_); } - - private: - OnHelperGroup(Q q, JoinedQuery &jq) noexcept : q_{std::forward(q)}, jq_{jq} {} - Q q_; - JoinedQuery &jq_; - OpType op_{OpAnd}; - friend class OnHelperTempl; - }; - template - class OnHelperTempl { - public: - OnHelperTempl &&Not() &&noexcept { - op_ = OpNot; - return std::move(*this); - } - Q On(std::string index, CondType cond, std::string joinIndex) &&; - OnHelperGroup OpenBracket() &&noexcept { return {std::forward(q_), jq_}; } - - private: - OnHelperTempl(Q q, JoinedQuery &jq) noexcept : q_{std::forward(q)}, jq_{jq} {} - Q q_; - JoinedQuery &jq_; - OpType op_{OpAnd}; - friend class Query; - }; - using OnHelper = OnHelperTempl; - using OnHelperR = OnHelperTempl; - public: /// Creates an object for certain namespace with appropriate settings. /// @param nsName - name of the namespace the data to be selected from. /// @param start - number of the first row to get from selected set. Analog to sql OFFSET Offset. /// @param count - number of rows to get from result set. Analog to sql LIMIT RowsCount. /// @param calcTotal - calculation mode. - template - explicit Query(T nsName, unsigned start = QueryEntry::kDefaultOffset, unsigned count = QueryEntry::kDefaultLimit, + template > * = nullptr> + explicit Query(Str &&nsName, unsigned start = QueryEntry::kDefaultOffset, unsigned count = QueryEntry::kDefaultLimit, CalcTotalMode calcTotal = ModeNoTotal) - : namespace_(std::forward(nsName)), start_(start), count_(count), calcTotal_(calcTotal) {} + : namespace_(std::forward(nsName)), start_(start), count_(count), calcTotal_(calcTotal) {} - /// Creates an empty object. Query() = default; /// Allows to compare 2 Query objects. - bool operator==(const Query &) const; + [[nodiscard]] bool operator==(const Query &) const; /// Parses pure sql select query and initializes Query object data members as a result. /// @param q - sql query. - void FromSQL(std::string_view q); + [[nodiscard]] static Query FromSQL(std::string_view q); /// Logs query in 'Select field1, ... field N from namespace ...' format. /// @param ser - serializer to store SQL string /// @param stripArgs - replace condition values with '?' WrSerializer &GetSQL(WrSerializer &ser, bool stripArgs = false) const; + /// Logs query in 'Select field1, ... field N from namespace ...' format. + /// @param ser - serializer to store SQL string + /// @param realType - replaces original query's type + /// @param stripArgs - replace condition values with '?' + WrSerializer &GetSQL(WrSerializer &ser, QueryType realType, bool stripArgs = false) const; + /// Logs query in 'Select field1, ... field N from namespace ...' format. /// @param stripArgs - replace condition values with '?' /// @return Query in SQL format - std::string GetSQL(bool stripArgs = false) const; + [[nodiscard]] std::string GetSQL(bool stripArgs = false) const; /// Logs query in 'Select field1, ... field N from namespace ...' format. /// @param realType - replaces original query's type /// @return Query in SQL format - std::string GetSQL(QueryType realType) const; + [[nodiscard]] std::string GetSQL(QueryType realType) const; /// Parses JSON dsl set. /// @param dsl - dsl set. /// @return always returns errOk or throws an exception. - Error FromJSON(const std::string &dsl); + [[nodiscard]] Error FromJSON(std::string_view dsl); /// returns structure of a query in JSON dsl format - std::string GetJSON() const; + [[nodiscard]] std::string GetJSON() const; /// Enable explain query /// @param on - signaling on/off /// @return Query object ready to be executed - Query &Explain(bool on = true) & { - explain_ = on; + Query &Explain(bool on = true) & noexcept { + walkNested(true, true, true, [on](Query &q) noexcept { q.explain_ = on; }); return *this; } - Query &&Explain(bool on = true) && { return std::move(Explain(on)); } + [[nodiscard]] Query &&Explain(bool on = true) && noexcept { return std::move(Explain(on)); } + [[nodiscard]] bool GetExplain() const noexcept { return explain_; } /// Adds a condition with a single value. Analog to sql Where clause. /// @param field - field used in condition clause. /// @param cond - type of condition. /// @param val - value of index to be compared with. /// @return Query object ready to be executed. - template + template > * = nullptr> Query &Where(Str &&field, CondType cond, Input val) & { return Where(std::forward(field), cond, {std::forward(val)}); } - template - Query &&Where(Str &&field, CondType cond, Input val) && { + template > * = nullptr> + [[nodiscard]] Query &&Where(Str &&field, CondType cond, Input val) && { return std::move(Where(std::forward(field), cond, {std::move(val)})); } @@ -137,17 +100,17 @@ class Query { /// @param cond - type of condition. /// @param l - list of index values to be compared with. /// @return Query object ready to be executed. - template + template > * = nullptr> Query &Where(Str &&field, CondType cond, std::initializer_list l) & { VariantArray values; values.reserve(l.size()); for (auto it = l.begin(); it != l.end(); it++) values.emplace_back(*it); - entries.Append(nextOp_, std::forward(field), cond, std::move(values)); + entries_.Append(nextOp_, std::forward(field), cond, std::move(values)); nextOp_ = OpAnd; return *this; } - template - Query &&Where(Str &&field, CondType cond, std::initializer_list l) && { + template > * = nullptr> + [[nodiscard]] Query &&Where(Str &&field, CondType cond, std::initializer_list l) && { return std::move(Where(std::forward(field), cond, std::move(l))); } @@ -156,17 +119,17 @@ class Query { /// @param cond - type of condition. /// @param l - vector of index values to be compared with. /// @return Query object ready to be executed. - template + template > * = nullptr> Query &Where(Str &&field, CondType cond, const std::vector &l) & { VariantArray values; values.reserve(l.size()); for (auto it = l.begin(); it != l.end(); it++) values.emplace_back(*it); - entries.Append(nextOp_, std::forward(field), cond, std::move(values)); + entries_.Append(nextOp_, std::forward(field), cond, std::move(values)); nextOp_ = OpAnd; return *this; } - template - Query &&Where(Str &&field, CondType cond, const std::vector &l) && { + template > * = nullptr> + [[nodiscard]] Query &&Where(Str &&field, CondType cond, const std::vector &l) && { return std::move(Where(std::forward(field), cond, l)); } @@ -175,14 +138,14 @@ class Query { /// @param cond - type of condition. /// @param l - vector of index values to be compared with. /// @return Query object ready to be executed. - template + template > * = nullptr> Query &Where(Str &&field, CondType cond, VariantArray l) & { - entries.Append(nextOp_, std::forward(field), cond, std::move(l)); + entries_.Append(nextOp_, std::forward(field), cond, std::move(l)); nextOp_ = OpAnd; return *this; } - template - Query &&Where(Str &&field, CondType cond, VariantArray l) && { + template > * = nullptr> + [[nodiscard]] Query &&Where(Str &&field, CondType cond, VariantArray l) && { return std::move(Where(std::forward(field), cond, std::move(l))); } @@ -197,160 +160,222 @@ class Query { /// in case of CondRange) belongs to "bookid" and l[0][1] (and l[1][1] in case of CondRange) /// belongs to "price" indexes. /// @return Query object ready to be executed. - template + template > * = nullptr> Query &WhereComposite(Str &&idx, CondType cond, std::initializer_list l) & { VariantArray values; values.reserve(l.size()); for (auto it = l.begin(); it != l.end(); it++) { values.emplace_back(*it); } - entries.Append(nextOp_, std::forward(idx), cond, std::move(values)); + entries_.Append(nextOp_, std::forward(idx), cond, std::move(values)); nextOp_ = OpAnd; return *this; } - template - Query &&WhereComposite(Str &&idx, CondType cond, std::initializer_list l) && { + template > * = nullptr> + [[nodiscard]] Query &&WhereComposite(Str &&idx, CondType cond, std::initializer_list l) && { return std::move(WhereComposite(std::forward(idx), cond, std::move(l))); } - template + template > * = nullptr> Query &WhereComposite(Str &&idx, CondType cond, const std::vector &v) & { VariantArray values; values.reserve(v.size()); for (auto it = v.begin(); it != v.end(); it++) { values.emplace_back(*it); } - entries.Append(nextOp_, std::forward(idx), cond, std::move(values)); + entries_.Append(nextOp_, std::forward(idx), cond, std::move(values)); nextOp_ = OpAnd; return *this; } - template - Query &&WhereComposite(Str &&idx, CondType cond, const std::vector &v) && { + template > * = nullptr> + [[nodiscard]] Query &&WhereComposite(Str &&idx, CondType cond, const std::vector &v) && { return std::move(WhereComposite(std::forward(idx), cond, v)); } template Query &WhereBetweenFields(Str1 &&firstIdx, CondType cond, Str2 &&secondIdx) & { - entries.Append(nextOp_, std::forward(firstIdx), cond, std::forward(secondIdx)); + entries_.Append(nextOp_, std::forward(firstIdx), cond, std::forward(secondIdx)); nextOp_ = OpAnd; return *this; } template - Query &&WhereBetweenFields(Str1 &&firstIdx, CondType cond, Str2 &&secondIdx) && { + [[nodiscard]] Query &&WhereBetweenFields(Str1 &&firstIdx, CondType cond, Str2 &&secondIdx) && { return std::move(WhereBetweenFields(std::forward(firstIdx), cond, std::forward(secondIdx))); } - template + template > * = nullptr> Query &DWithin(Str &&field, Point p, double distance) & { - entries.Append(nextOp_, std::forward(field), CondDWithin, VariantArray::Create(p, distance)); + entries_.Append(nextOp_, std::forward(field), CondDWithin, VariantArray::Create(p, distance)); nextOp_ = OpAnd; return *this; } - template - Query &&DWithin(Str &&field, Point p, double distance) && { + template > * = nullptr> + [[nodiscard]] Query &&DWithin(Str &&field, Point p, double distance) && { return std::move(DWithin(std::forward(field), p, distance)); } + Query &DWithin(Query &&q, Point p, double distance) & { return Where(std::move(q), CondDWithin, VariantArray::Create(p, distance)); } + [[nodiscard]] Query &&DWithin(Query &&q, Point p, double distance) && { return std::move(DWithin(std::move(q), p, distance)); } + Query &Where(Query &&q, CondType cond, VariantArray &&values) & { + if (cond == CondEmpty || cond == CondAny) { + q.checkSubQueryNoData(); + q.Limit(0); + } else { + q.checkSubQueryWithData(); + if (!q.selectFilter_.empty() && !q.HasLimit() && !q.HasOffset()) { + q.sortingEntries_.clear(); + q.Where(q.selectFilter_[0], cond, std::move(values)); + q.selectFilter_.clear(); + return Where(std::move(q), CondAny, {}); + } else if (q.HasCalcTotal() || (!q.aggregations_.empty() && + (q.aggregations_[0].Type() == AggCount || q.aggregations_[0].Type() == AggCountCached))) { + q.Limit(0); + } + } + q.Strict(strictMode_).Debug(debugLevel_).Explain(explain_); + entries_.Append(nextOp_, cond, subQueries_.size(), std::move(values)); + PopBackQEGuard guard{&entries_}; + adoptNested(q); + subQueries_.emplace_back(std::move(q)); + guard.Reset(); + nextOp_ = OpAnd; + return *this; + } + [[nodiscard]] Query &&Where(Query &&q, CondType cond, VariantArray &&values) && { + return std::move(Where(std::move(q), cond, std::move(values))); + } + template + Query &Where(Query &&q, CondType cond, std::initializer_list values) & { + return Where(std::move(q), cond, VariantArray::Create(values)); + } + template + [[nodiscard]] Query &&Where(Query &&q, CondType cond, std::initializer_list values) && { + return std::move(Where(std::move(q), cond, VariantArray::Create(values))); + } + + template > * = nullptr> + Query &Where(Str &&field, CondType cond, Query &&q) & { + if (cond == CondDWithin) { + throw Error(errQueryExec, "DWithin between field and subquery"); + } + q.checkSubQueryWithData(); + adoptNested(q); + if (q.HasCalcTotal() || + (!q.aggregations_.empty() && (q.aggregations_[0].Type() == AggCount || q.aggregations_[0].Type() == AggCountCached))) { + q.Limit(0); + } + entries_.Append(nextOp_, std::forward(field), cond, subQueries_.size()); + PopBackQEGuard guard{&entries_}; + adoptNested(q); + subQueries_.emplace_back(std::move(q)); + guard.Reset(); + nextOp_ = OpAnd; + return *this; + } + template > * = nullptr> + [[nodiscard]] Query &&Where(Str &&field, CondType cond, Query &&q) && { + return std::move(Where(std::forward(field), cond, std::move(q))); + } /// Sets a new value for a field. /// @param field - field name. /// @param value - new value. /// @param hasExpressions - true: value has expresions in it - template + template > * = nullptr> Query &Set(Str &&field, ValueType value, bool hasExpressions = false) & { return Set(std::forward(field), {value}, hasExpressions); } - template - Query &&Set(Str &&field, ValueType value, bool hasExpressions = false) && { + template > * = nullptr> + [[nodiscard]] Query &&Set(Str &&field, ValueType value, bool hasExpressions = false) && { return std::move(Set(std::forward(field), std::move(value), hasExpressions)); } /// Sets a new value for a field. /// @param field - field name. /// @param l - new value. /// @param hasExpressions - true: value has expresions in it - template + template > * = nullptr> Query &Set(Str &&field, std::initializer_list l, bool hasExpressions = false) & { VariantArray value; value.reserve(l.size()); for (auto it = l.begin(); it != l.end(); it++) value.emplace_back(*it); return Set(std::forward(field), std::move(value), hasExpressions); } - template - Query &&Set(Str &&field, std::initializer_list l, bool hasExpressions = false) && { + template > * = nullptr> + [[nodiscard]] Query &&Set(Str &&field, std::initializer_list l, bool hasExpressions = false) && { return std::move(Set(std::forward(field), std::move(l), hasExpressions)); } /// Sets a new value for a field. /// @param field - field name. /// @param l - new value. /// @param hasExpressions - true: value has expresions in it - template + template > * = nullptr> Query &Set(Str &&field, const std::vector &l, bool hasExpressions = false) & { VariantArray value; value.reserve(l.size()); for (auto it = l.begin(); it != l.end(); it++) value.emplace_back(*it); return Set(std::forward(field), std::move(value.MarkArray()), hasExpressions); } - template - Query &&Set(Str &&field, const std::vector &l, bool hasExpressions = false) && { + template > * = nullptr> + [[nodiscard]] Query &&Set(Str &&field, const std::vector &l, bool hasExpressions = false) && { return std::move(Set(std::forward(field), l, hasExpressions)); } /// Sets a new value for a field. /// @param field - field name. /// @param value - new value. /// @param hasExpressions - true: value has expresions in it - template + template > * = nullptr> Query &Set(Str &&field, VariantArray value, bool hasExpressions = false) & { updateFields_.emplace_back(std::forward(field), std::move(value), FieldModeSet, hasExpressions); return *this; } - template - Query &&Set(Str &&field, VariantArray value, bool hasExpressions = false) && { + template > * = nullptr> + [[nodiscard]] Query &&Set(Str &&field, VariantArray value, bool hasExpressions = false) && { return std::move(Set(std::forward(field), std::move(value), hasExpressions)); } /// Sets a value for a field as an object. /// @param field - field name. /// @param value - new value. /// @param hasExpressions - true: value has expresions in it - template + template > * = nullptr> Query &SetObject(Str &&field, ValueType value, bool hasExpressions = false) & { return SetObject(std::forward(field), {value}, hasExpressions); } - template - Query &&SetObject(Str &&field, ValueType value, bool hasExpressions = false) && { + template > * = nullptr> + [[nodiscard]] Query &&SetObject(Str &&field, ValueType value, bool hasExpressions = false) && { return std::move(SetObject(std::forward(field), std::move(value), hasExpressions)); } /// Sets a new value for a field as an object. /// @param field - field name. /// @param l - new value. /// @param hasExpressions - true: value has expresions in it - template + template > * = nullptr> Query &SetObject(Str &&field, std::initializer_list l, bool hasExpressions = false) & { VariantArray value; value.reserve(l.size()); for (auto it = l.begin(); it != l.end(); it++) value.emplace_back(*it); return SetObject(std::forward(field), std::move(value), hasExpressions); } - template - Query &&SetObject(Str &&field, std::initializer_list l, bool hasExpressions = false) && { + template > * = nullptr> + [[nodiscard]] Query &&SetObject(Str &&field, std::initializer_list l, bool hasExpressions = false) && { return std::move(SetObject(std::forward(field), std::move(l), hasExpressions)); } /// Sets a new value for a field as an object. /// @param field - field name. /// @param l - new value. /// @param hasExpressions - true: value has expresions in it - template + template > * = nullptr> Query &SetObject(Str &&field, const std::vector &l, bool hasExpressions = false) & { VariantArray value; value.reserve(l.size()); for (auto it = l.begin(); it != l.end(); it++) value.emplace_back(Variant(*it)); return SetObject(std::forward(field), std::move(value.MarkArray()), hasExpressions); } - template - Query &&SetObject(Str &&field, const std::vector &l, bool hasExpressions = false) && { + template > * = nullptr> + [[nodiscard]] Query &&SetObject(Str &&field, const std::vector &l, bool hasExpressions = false) && { return std::move(SetObject(std::forward(field), l, hasExpressions)); } /// Sets a value for a field as an object. /// @param field - field name. /// @param value - new value. /// @param hasExpressions - true: value has expresions in it - template + template > * = nullptr> Query &SetObject(Str &&field, VariantArray value, bool hasExpressions = false) & { for (auto &it : value) { if (!it.Type().Is()) { @@ -361,25 +386,25 @@ class Query { updateFields_.emplace_back(std::forward(field), std::move(value), FieldModeSetJson, hasExpressions); return *this; } - template - Query &&SetObject(Str &&field, VariantArray value, bool hasExpressions = false) && { + template > * = nullptr> + [[nodiscard]] Query &&SetObject(Str &&field, VariantArray value, bool hasExpressions = false) && { return std::move(SetObject(std::forward(field), std::move(value), hasExpressions)); } /// Drops a value for a field. /// @param field - field name. - template + template > * = nullptr> Query &Drop(Str &&field) & { updateFields_.emplace_back(std::forward(field), VariantArray(), FieldModeDrop); return *this; } - template - Query &&Drop(Str &&field) && { + template > * = nullptr> + [[nodiscard]] Query &&Drop(Str &&field) && { return std::move(Drop(std::forward(field))); } /// Add sql-function to query. /// @param function - function declaration. - template + template > * = nullptr> void AddFunction(Str &&function) { selectFunctions_.emplace_back(std::forward(function)); } @@ -387,26 +412,30 @@ class Query { /// Adds equal position fields to arrays queries. /// @param equalPosition - list of fields with equal array index position. Query &AddEqualPosition(h_vector equalPosition) & { - auto *const bracket = entries.LastOpenBracket(); - auto &eqPos = (bracket ? bracket->equalPositions : entries.equalPositions); + auto *const bracket = entries_.LastOpenBracket(); + auto &eqPos = (bracket ? bracket->equalPositions : entries_.equalPositions); eqPos.emplace_back(std::make_move_iterator(equalPosition.begin()), std::make_move_iterator(equalPosition.end())); return *this; } Query &AddEqualPosition(std::vector equalPosition) & { - auto *const bracket = entries.LastOpenBracket(); - auto &eqPos = (bracket ? bracket->equalPositions : entries.equalPositions); + auto *const bracket = entries_.LastOpenBracket(); + auto &eqPos = (bracket ? bracket->equalPositions : entries_.equalPositions); eqPos.emplace_back(std::make_move_iterator(equalPosition.begin()), std::make_move_iterator(equalPosition.end())); return *this; } Query &AddEqualPosition(std::initializer_list l) & { - auto *const bracket = entries.LastOpenBracket(); - auto &eqPos = (bracket ? bracket->equalPositions : entries.equalPositions); + auto *const bracket = entries_.LastOpenBracket(); + auto &eqPos = (bracket ? bracket->equalPositions : entries_.equalPositions); eqPos.emplace_back(l); return *this; } - Query &&AddEqualPosition(h_vector equalPosition) && { return std::move(AddEqualPosition(std::move(equalPosition))); } - Query &&AddEqualPosition(std::vector equalPosition) && { return std::move(AddEqualPosition(std::move(equalPosition))); } - Query &&AddEqualPosition(std::initializer_list l) && { return std::move(AddEqualPosition(l)); } + [[nodiscard]] Query &&AddEqualPosition(h_vector equalPosition) && { + return std::move(AddEqualPosition(std::move(equalPosition))); + } + [[nodiscard]] Query &&AddEqualPosition(std::vector equalPosition) && { + return std::move(AddEqualPosition(std::move(equalPosition))); + } + [[nodiscard]] Query &&AddEqualPosition(std::initializer_list l) && { return std::move(AddEqualPosition(l)); } /// Joins namespace with another namespace. Analog to sql JOIN. /// @param joinType - type of Join (Inner, Left or OrInner). @@ -418,19 +447,19 @@ class Query { /// @return Query object ready to be executed. Query &Join(JoinType joinType, std::string leftField, std::string rightField, CondType cond, OpType op, Query &&qr) &; template - Query &&Join(JoinType joinType, StrL &&leftField, StrR &&rightField, CondType cond, OpType op, Query &&qr) && { + [[nodiscard]] Query &&Join(JoinType joinType, StrL &&leftField, StrR &&rightField, CondType cond, OpType op, Query &&qr) && { return std::move(Join(joinType, std::forward(leftField), std::forward(rightField), cond, op, std::move(qr))); } Query &Join(JoinType joinType, std::string leftField, std::string rightField, CondType cond, OpType op, const Query &qr) &; template - Query &&Join(JoinType joinType, StrL &&leftField, StrR &&rightField, CondType cond, OpType op, const Query &qr) && { + [[nodiscard]] Query &&Join(JoinType joinType, StrL &&leftField, StrR &&rightField, CondType cond, OpType op, const Query &qr) && { return std::move(Join(joinType, std::forward(leftField), std::forward(rightField), cond, op, qr)); } - OnHelper Join(JoinType joinType, Query &&q) &; - OnHelper Join(JoinType joinType, const Query &q) &; - OnHelperR Join(JoinType joinType, Query &&q) &&; - OnHelperR Join(JoinType joinType, const Query &q) &&; + [[nodiscard]] auto Join(JoinType joinType, Query &&q) &; + [[nodiscard]] auto Join(JoinType joinType, const Query &q) &; + [[nodiscard]] auto Join(JoinType joinType, Query &&q) &&; + [[nodiscard]] auto Join(JoinType joinType, const Query &q) &&; /// @public /// Inner Join of this namespace with another one. @@ -444,7 +473,7 @@ class Query { return Join(JoinType::InnerJoin, std::forward(leftField), std::forward(rightField), cond, OpAnd, std::move(qr)); } template - Query &&InnerJoin(StrL &&leftField, StrR &&rightField, CondType cond, Query &&qr) && { + [[nodiscard]] Query &&InnerJoin(StrL &&leftField, StrR &&rightField, CondType cond, Query &&qr) && { return std::move(InnerJoin(std::forward(leftField), std::forward(rightField), cond, std::move(qr))); } template @@ -452,7 +481,7 @@ class Query { return Join(JoinType::InnerJoin, std::forward(leftField), std::forward(rightField), cond, OpAnd, qr); } template - Query &&InnerJoin(StrL &&leftField, StrR &&rightField, CondType cond, const Query &qr) && { + [[nodiscard]] Query &&InnerJoin(StrL &&leftField, StrR &&rightField, CondType cond, const Query &qr) && { return std::move(InnerJoin(std::forward(leftField), std::forward(rightField), cond, qr)); } @@ -467,7 +496,7 @@ class Query { return Join(JoinType::LeftJoin, std::forward(leftField), std::forward(rightField), cond, OpAnd, std::move(qr)); } template - Query &&LeftJoin(StrL &&leftField, StrR &&rightField, CondType cond, Query &&qr) && { + [[nodiscard]] Query &&LeftJoin(StrL &&leftField, StrR &&rightField, CondType cond, Query &&qr) && { return std::move(LeftJoin(std::forward(leftField), std::forward(rightField), cond, std::move(qr))); } template @@ -475,7 +504,7 @@ class Query { return Join(JoinType::LeftJoin, std::forward(leftField), std::forward(rightField), cond, OpAnd, qr); } template - Query &&LeftJoin(StrL &&leftField, StrR &&rightField, CondType cond, const Query &qr) && { + [[nodiscard]] Query &&LeftJoin(StrL &&leftField, StrR &&rightField, CondType cond, const Query &qr) && { return std::move(LeftJoin(std::forward(leftField), std::forward(rightField), cond, qr)); } @@ -490,7 +519,7 @@ class Query { return Join(JoinType::OrInnerJoin, std::forward(leftField), std::forward(rightField), cond, OpAnd, std::move(qr)); } template - Query &&OrInnerJoin(StrL &&leftField, StrR &&rightField, CondType cond, Query &&qr) && { + [[nodiscard]] Query &&OrInnerJoin(StrL &&leftField, StrR &&rightField, CondType cond, Query &&qr) && { return std::move(OrInnerJoin(std::forward(leftField), std::forward(rightField), cond, std::move(qr))); } template @@ -498,43 +527,45 @@ class Query { return Join(JoinType::OrInnerJoin, std::forward(leftField), std::forward(rightField), cond, OpAnd, qr); } template - Query &&OrInnerJoin(StrL &&leftField, StrR &&rightField, CondType cond, const Query &qr) && { + [[nodiscard]] Query &&OrInnerJoin(StrL &&leftField, StrR &&rightField, CondType cond, const Query &qr) && { return std::move(OrInnerJoin(std::forward(leftField), std::forward(rightField), cond, qr)); } Query &Merge(const Query &q) &; - Query &&Merge(const Query &q) && { return std::move(Merge(q)); } + [[nodiscard]] Query &&Merge(const Query &q) && { return std::move(Merge(q)); } Query &Merge(Query &&q) &; - Query &&Merge(Query &&q) && { return std::move(Merge(std::move(q))); } + [[nodiscard]] Query &&Merge(Query &&q) && { return std::move(Merge(std::move(q))); } /// Changes debug level. /// @param level - debug level. /// @return Query object. - Query &Debug(int level) &noexcept { - debugLevel = level; + Query &Debug(int level) & noexcept { + walkNested(true, true, true, [level](Query &q) noexcept { q.debugLevel_ = level; }); return *this; } - Query &&Debug(int level) &&noexcept { return std::move(Debug(level)); } + [[nodiscard]] Query &&Debug(int level) && noexcept { return std::move(Debug(level)); } + [[nodiscard]] int GetDebugLevel() const noexcept { return debugLevel_; } /// Changes strict mode. /// @param mode - strict mode. /// @return Query object. - Query &Strict(StrictMode mode) &noexcept { - strictMode = mode; + Query &Strict(StrictMode mode) & noexcept { + walkNested(true, true, true, [mode](Query &q) noexcept { q.strictMode_ = mode; }); return *this; } - Query &&Strict(StrictMode mode) &&noexcept { return std::move(Strict(mode)); } + [[nodiscard]] Query &&Strict(StrictMode mode) && noexcept { return std::move(Strict(mode)); } + [[nodiscard]] StrictMode GetStrictMode() const noexcept { return strictMode_; } /// Performs sorting by certain column. Same as sql 'ORDER BY'. /// @param sort - sorting column name. /// @param desc - is sorting direction descending or ascending. /// @return Query object. - template + template > * = nullptr> Query &Sort(Str &&sort, bool desc) & { // -V1071 if (!strEmpty(sort)) sortingEntries_.emplace_back(std::forward(sort), desc); return *this; } - template - Query &&Sort(Str &&sort, bool desc) && { + template > * = nullptr> + [[nodiscard]] Query &&Sort(Str &&sort, bool desc) && { return std::move(Sort(std::forward(sort), desc)); } @@ -544,14 +575,16 @@ class Query { /// @param desc - is sorting direction descending or ascending. /// @return Query object. Query &SortStDistance(std::string_view field, reindexer::Point p, bool desc) &; - Query &&SortStDistance(std::string_view field, reindexer::Point p, bool desc) && { return std::move(SortStDistance(field, p, desc)); } + [[nodiscard]] Query &&SortStDistance(std::string_view field, reindexer::Point p, bool desc) && { + return std::move(SortStDistance(field, p, desc)); + } /// Performs sorting by ST_Distance() expressions for geometry index. Sorting function will use distance 2 fields. /// @param field1 - first field name. This field must contain Point. /// @param field2 - second field name.This field must contain Point. /// @param desc - is sorting direction descending or ascending. /// @return Query object. Query &SortStDistance(std::string_view field1, std::string_view field2, bool desc) &; - Query &&SortStDistance(std::string_view field1, std::string_view field2, bool desc) && { + [[nodiscard]] Query &&SortStDistance(std::string_view field1, std::string_view field2, bool desc) && { return std::move(SortStDistance(field1, field2, desc)); } @@ -560,7 +593,7 @@ class Query { /// @param desc - is sorting direction descending or ascending. /// @param forcedSortOrder - list of values for forced sort order. /// @return Query object. - template + template > * = nullptr> Query &Sort(Str &&sort, bool desc, std::initializer_list forcedSortOrder) & { if (!sortingEntries_.empty() && !std::empty(forcedSortOrder)) throw Error(errParams, "Forced sort order is allowed for the first sorting entry only"); @@ -568,8 +601,8 @@ class Query { for (const T &v : forcedSortOrder) forcedSortOrder_.emplace_back(v); return *this; } - template - Query &&Sort(Str &&sort, bool desc, std::initializer_list forcedSortOrder) && { + template > * = nullptr> + [[nodiscard]] Query &&Sort(Str &&sort, bool desc, std::initializer_list forcedSortOrder) && { return std::move(Sort(std::forward(sort), desc, std::move(forcedSortOrder))); } @@ -578,7 +611,7 @@ class Query { /// @param desc - is sorting direction descending or ascending. /// @param forcedSortOrder - list of values for forced sort order. /// @return Query object. - template + template > * = nullptr> Query &Sort(Str &&sort, bool desc, const T &forcedSortOrder) & { if (!sortingEntries_.empty() && !forcedSortOrder.empty()) throw Error(errParams, "Forced sort order is allowed for the first sorting entry only"); @@ -586,35 +619,51 @@ class Query { for (const auto &v : forcedSortOrder) forcedSortOrder_.emplace_back(v); return *this; } - template - Query &&Sort(Str &&sort, bool desc, const T &forcedSortOrder) && { + template > * = nullptr> + [[nodiscard]] Query &&Sort(Str &&sort, bool desc, const T &forcedSortOrder) && { return std::move(Sort(std::forward(sort), desc, forcedSortOrder)); } /// Performs distinct for a certain index. /// @param indexName - name of index for distict operation. - template + template > * = nullptr> Query &Distinct(Str &&indexName) & { if (!strEmpty(indexName)) { aggregations_.emplace_back(AggDistinct, h_vector{std::forward(indexName)}); } return *this; } - template - Query &&Distinct(Str &&indexName) && { + template > * = nullptr> + [[nodiscard]] Query &&Distinct(Str &&indexName) && { return std::move(Distinct(std::forward(indexName))); } /// Sets list of columns in this namespace to be finally selected. /// @param l - list of columns to be selected. - Query &Select(std::initializer_list l) & { + template > * = nullptr> + Query &Select(std::initializer_list l) & { + return Select>(std::move(l)); + } + template > * = nullptr> + [[nodiscard]] Query &&Select(std::initializer_list l) && { + return std::move(Select>(std::move(l))); + } + + template + Query &Select(StrCont &&l) & { + using namespace std::string_view_literals; if (!CanAddSelectFilter()) { throw Error(errConflict, kAggregationWithSelectFieldsMsgError); } selectFilter_.insert(selectFilter_.begin(), l.begin(), l.end()); + selectFilter_.erase(std::remove_if(selectFilter_.begin(), selectFilter_.end(), [](const auto &s) { return s == "*"sv; }), + selectFilter_.end()); return *this; } - Query &&Select(std::initializer_list l) && { return std::move(Select(l)); } + template + [[nodiscard]] Query &&Select(StrCont &&l) && { + return std::move(Select(std::forward(l))); + } /// Adds an aggregate function for certain column. /// Analog to sql aggregate functions (min, max, avg, etc). @@ -638,95 +687,111 @@ class Query { aggregations_.emplace_back(type, std::move(fields), std::move(sorting), limit, offset); return *this; } - Query &&Aggregate(AggType type, h_vector fields, const std::vector> &sort = {}, - unsigned limit = QueryEntry::kDefaultLimit, unsigned offset = QueryEntry::kDefaultOffset) && { + [[nodiscard]] Query &&Aggregate(AggType type, h_vector fields, + const std::vector> &sort = {}, unsigned limit = QueryEntry::kDefaultLimit, + unsigned offset = QueryEntry::kDefaultOffset) && { return std::move(Aggregate(type, std::move(fields), sort, limit, offset)); } /// Sets next operation type to Or. /// @return Query object. Query &Or() & { + assertrx_dbg(nextOp_ == OpAnd); nextOp_ = OpOr; return *this; } - Query &&Or() && { return std::move(Or()); } + [[nodiscard]] Query &&Or() && { return std::move(Or()); } /// Sets next operation type to Not. /// @return Query object. Query &Not() & { + assertrx_dbg(nextOp_ == OpAnd); nextOp_ = OpNot; return *this; } - Query &&Not() && { return std::move(Not()); } + [[nodiscard]] Query &&Not() && { return std::move(Not()); } + /// Sets next operation type to And. + /// @return Query object. + Query &And() & { + nextOp_ = OpAnd; + return *this; + } + [[nodiscard]] Query &&And() && { return std::move(And()); } + Query &NextOp(OpType op) & { + nextOp_ = op; + return *this; + } + [[nodiscard]] Query &&NextOp(OpType op) && { return std::move(NextOp(op)); } + [[nodiscard]] OpType NextOp() const noexcept { return nextOp_; } /// Insert open bracket to order logic operations. /// @return Query object. Query &OpenBracket() & { - entries.OpenBracket(nextOp_); + entries_.OpenBracket(nextOp_); nextOp_ = OpAnd; return *this; } - Query &&OpenBracket() && { return std::move(OpenBracket()); } + [[nodiscard]] Query &&OpenBracket() && { return std::move(OpenBracket()); } /// Insert close bracket to order logic operations. /// @return Query object. Query &CloseBracket() & { - entries.CloseBracket(); + entries_.CloseBracket(); return *this; } - Query &&CloseBracket() && { return std::move(CloseBracket()); } + [[nodiscard]] Query &&CloseBracket() && { return std::move(CloseBracket()); } /// Sets the limit of selected rows. /// Analog to sql LIMIT rowsNumber. /// @param limit - number of rows to get from result set. /// @return Query object. - Query &Limit(unsigned limit) &noexcept { + Query &Limit(unsigned limit) & noexcept { count_ = limit; return *this; } - Query &&Limit(unsigned limit) &&noexcept { return std::move(Limit(limit)); } + [[nodiscard]] Query &&Limit(unsigned limit) && noexcept { return std::move(Limit(limit)); } /// Sets the number of the first selected row from result query. /// Analog to sql LIMIT OFFSET. /// @param offset - index of the first row to get from result set. /// @return Query object. - Query &Offset(unsigned offset) &noexcept { + Query &Offset(unsigned offset) & noexcept { start_ = offset; return *this; } - Query &&Offset(unsigned offset) &&noexcept { return std::move(Offset(offset)); } + [[nodiscard]] Query &&Offset(unsigned offset) && noexcept { return std::move(Offset(offset)); } /// Set the total count calculation mode to Accurate /// @return Query object - Query &ReqTotal() &noexcept { + Query &ReqTotal() & noexcept { calcTotal_ = ModeAccurateTotal; return *this; } - Query &&ReqTotal() &&noexcept { return std::move(ReqTotal()); } + [[nodiscard]] Query &&ReqTotal() && noexcept { return std::move(ReqTotal()); } /// Set the total count calculation mode to Cached. /// It will be use LRUCache for total count result /// @return Query object - Query &CachedTotal() &noexcept { + Query &CachedTotal() & noexcept { calcTotal_ = ModeCachedTotal; return *this; } - Query &&CachedTotal() &&noexcept { return std::move(CachedTotal()); } + [[nodiscard]] Query &&CachedTotal() && noexcept { return std::move(CachedTotal()); } /// Output fulltext rank /// Allowed only with fulltext query /// @return Query object - Query &WithRank() &noexcept { + Query &WithRank() & noexcept { withRank_ = true; return *this; } - Query &&WithRank() &&noexcept { return std::move(WithRank()); } - bool IsWithRank() const noexcept { return withRank_; } + [[nodiscard]] Query &&WithRank() && noexcept { return std::move(WithRank()); } + [[nodiscard]] bool IsWithRank() const noexcept { return withRank_; } /// Can we add aggregation functions /// or new select fields to a current query? - bool CanAddAggregation(AggType type) const noexcept { return type == AggDistinct || (selectFilter_.empty()); } - bool CanAddSelectFilter() const noexcept { + [[nodiscard]] bool CanAddAggregation(AggType type) const noexcept { return type == AggDistinct || (selectFilter_.empty()); } + [[nodiscard]] bool CanAddSelectFilter() const noexcept { return aggregations_.empty() || (aggregations_.size() == 1 && aggregations_.front().Type() == AggDistinct); } @@ -737,78 +802,200 @@ class Query { /// Deserializes query data from stream. /// @param ser - serializer object. - void Deserialize(Serializer &ser); + [[nodiscard]] static Query Deserialize(Serializer &ser); - void WalkNested(bool withSelf, bool withMerged, const std::function &visitor) const; + void WalkNested(bool withSelf, bool withMerged, bool withSubQueries, const std::function &visitor) const + noexcept(noexcept(visitor(std::declval()))); - bool HasLimit() const noexcept { return count_ != QueryEntry::kDefaultLimit; } - bool HasOffset() const noexcept { return start_ != QueryEntry::kDefaultOffset; } - bool IsWALQuery() const noexcept; - const std::vector &UpdateFields() const noexcept { return updateFields_; } - QueryType Type() const noexcept { return type_; } - const std::string &NsName() const &noexcept { return namespace_; } + [[nodiscard]] bool HasLimit() const noexcept { return count_ != QueryEntry::kDefaultLimit; } + [[nodiscard]] bool HasOffset() const noexcept { return start_ != QueryEntry::kDefaultOffset; } + [[nodiscard]] bool IsWALQuery() const noexcept; + [[nodiscard]] const std::vector &UpdateFields() const noexcept { return updateFields_; } + [[nodiscard]] QueryType Type() const noexcept { return type_; } + [[nodiscard]] const std::string &NsName() const & noexcept { return namespace_; } template - void SetNsName(T &&nsName) &noexcept { + void SetNsName(T &&nsName) & noexcept { namespace_ = std::forward(nsName); } - unsigned Limit() const noexcept { return count_; } - unsigned Offset() const noexcept { return start_; } - CalcTotalMode CalcTotal() const noexcept { return calcTotal_; } + [[nodiscard]] unsigned Limit() const noexcept { return count_; } + [[nodiscard]] unsigned Offset() const noexcept { return start_; } + [[nodiscard]] CalcTotalMode CalcTotal() const noexcept { return calcTotal_; } + [[nodiscard]] bool HasCalcTotal() const noexcept { return calcTotal_ != ModeNoTotal; } void CalcTotal(CalcTotalMode calcTotal) noexcept { calcTotal_ = calcTotal; } - int debugLevel = 0; /// Debug level. - StrictMode strictMode = StrictModeNotSet; /// Strict mode. - bool explain_ = false; /// Explain query if true QueryType type_ = QuerySelect; /// Query type - OpType nextOp_ = OpAnd; /// Next operation constant. SortingEntries sortingEntries_; /// Sorting data. std::vector forcedSortOrder_; /// Keys that always go first - before any ordered values. - std::vector joinQueries_; /// List of queries for join. - std::vector mergeQueries_; /// List of merge queries. - h_vector selectFilter_; /// List of columns in a final result set. std::vector selectFunctions_; /// List of sql functions - QueryEntries entries; - std::vector aggregations_; auto NsName() const && = delete; + [[nodiscard]] const QueryEntries &Entries() const noexcept { return entries_; } + template + [[nodiscard]] T &GetUpdatableEntry(size_t i) & noexcept { + return entries_.Get(i); + } + template + void SetEntry(size_t i, Args &&...args) { + entries_.SetValue(i, T{std::forward(args)...}); + } + void UpdateField(UpdateEntry &&ue) & { updateFields_.emplace_back(std::move(ue)); } + void SetEqualPositions(EqualPosition_t &&ep) & { entries_.equalPositions.emplace_back(std::move(ep)); } + void SetEqualPositions(size_t bracketPosition, EqualPosition_t &&ep) & { + entries_.Get(bracketPosition).equalPositions.emplace_back(std::move(ep)); + } + void Join(JoinedQuery &&) &; + void ReserveQueryEntries(size_t s) & { entries_.Reserve(s); } + template + Query &AppendQueryEntry(OpType op, Args &&...args) & { + entries_.Append(op, std::forward(args)...); + return *this; + } + template + Query &&AppendQueryEntry(OpType op, Args &&...args) && { + entries_.Append(op, std::forward(args)...); + return std::move(*this); + } + void SetLastOperation(OpType op) & { entries_.SetLastOperation(op); } + [[nodiscard]] const Query &GetSubQuery(size_t i) const & noexcept { return subQueries_.at(i); } + [[nodiscard]] const auto &GetSubQueries() const & noexcept { return subQueries_; } + [[nodiscard]] const auto &GetJoinQueries() const & noexcept { return joinQueries_; } + [[nodiscard]] const auto &GetMergeQueries() const & noexcept { return mergeQueries_; } + [[nodiscard]] const auto &SelectFilters() const & noexcept { return selectFilter_; } + void AddJoinQuery(JoinedQuery &&); + void VerifyForUpdate() const; + + auto GetSubQuery(size_t) const && = delete; + auto GetSubQueries() const && = delete; + auto GetJoinQueries() const && = delete; + auto GetMergeQueries() const && = delete; + auto SelectFilters() const && = delete; private: + class [[nodiscard]] PopBackQEGuard { + public: + explicit PopBackQEGuard(QueryEntries *e) noexcept : e_{e} {} + ~PopBackQEGuard() { + if (e_) e_->PopBack(); + } + void Reset() noexcept { e_ = nullptr; } + + private: + QueryEntries *e_; + }; + + template + class [[nodiscard]] OnHelperTempl; + template + class [[nodiscard]] OnHelperGroup { + public: + [[nodiscard]] OnHelperGroup &&Not() && noexcept { + op_ = OpNot; + return std::move(*this); + } + [[nodiscard]] OnHelperGroup &&Or() && noexcept { + op_ = OpOr; + return std::move(*this); + } + [[nodiscard]] OnHelperGroup &&On(std::string index, CondType cond, std::string joinIndex) &&; + [[nodiscard]] Q CloseBracket() && noexcept { return std::forward(q_); } + + private: + OnHelperGroup(Q q, JoinedQuery &jq) noexcept : q_{std::forward(q)}, jq_{jq} {} + Q q_; + JoinedQuery &jq_; + OpType op_{OpAnd}; + friend class OnHelperTempl; + }; + template + class [[nodiscard]] OnHelperTempl { + public: + [[nodiscard]] OnHelperTempl &&Not() && noexcept { + op_ = OpNot; + return std::move(*this); + } + [[nodiscard]] Q On(std::string index, CondType cond, std::string joinIndex) &&; + [[nodiscard]] OnHelperGroup OpenBracket() && noexcept { return {std::forward(q_), jq_}; } + + private: + OnHelperTempl(Q q, JoinedQuery &jq) noexcept : q_{std::forward(q)}, jq_{jq} {} + Q q_; + JoinedQuery &jq_; + OpType op_{OpAnd}; + friend class Query; + }; + using OnHelper = OnHelperTempl; + using OnHelperR = OnHelperTempl; + void deserialize(Serializer &ser, bool &hasJoinConditions); + VariantArray deserializeValues(Serializer &, CondType); + void checkSubQueryNoData() const; + void checkSubQueryWithData() const; + void checkSubQuery() const; + void walkNested(bool withSelf, bool withMerged, bool withSubQueries, + const std::function &visitor) noexcept(noexcept(visitor(std::declval()))); + void adoptNested(Query &nq) const noexcept { nq.Strict(GetStrictMode()).Explain(GetExplain()).Debug(GetDebugLevel()); } std::string namespace_; /// Name of the namespace. unsigned start_ = QueryEntry::kDefaultOffset; /// First row index from result set. unsigned count_ = QueryEntry::kDefaultLimit; /// Number of rows from result set. CalcTotalMode calcTotal_ = ModeNoTotal; /// Calculation mode. - std::vector updateFields_; /// List of fields (and values) for update. + QueryEntries entries_; + std::vector updateFields_; /// List of fields (and values) for update. + std::vector joinQueries_; /// List of queries for join. + std::vector mergeQueries_; /// List of merge queries. + std::vector subQueries_; + h_vector selectFilter_; /// List of columns in a final result set. bool withRank_ = false; - friend class SQLParser; + StrictMode strictMode_ = StrictModeNotSet; /// Strict mode. + int debugLevel_ = 0; /// Debug level. + bool explain_ = false; /// Explain query if true + OpType nextOp_ = OpAnd; /// Next operation constant. }; class JoinedQuery : public Query { public: - JoinedQuery() = default; JoinedQuery(JoinType jt, const Query &q) : Query(q), joinType{jt} {} JoinedQuery(JoinType jt, Query &&q) : Query(std::move(q)), joinType{jt} {} using Query::Query; - bool operator==(const JoinedQuery &obj) const; + [[nodiscard]] bool operator==(const JoinedQuery &obj) const; JoinType joinType{JoinType::LeftJoin}; /// Default join type. h_vector joinEntries_; /// Condition for join. Filled in each subqueries, empty in root query }; template -Q Query::OnHelperTempl::On(std::string index, CondType cond, std::string joinIndex) && { +[[nodiscard]] Q Query::OnHelperTempl::On(std::string index, CondType cond, std::string joinIndex) && { jq_.joinEntries_.emplace_back(op_, cond, std::move(index), std::move(joinIndex)); return std::forward(q_); } template -Query::OnHelperGroup &&Query::OnHelperGroup::On(std::string index, CondType cond, std::string joinIndex) && { +[[nodiscard]] Query::OnHelperGroup &&Query::OnHelperGroup::On(std::string index, CondType cond, std::string joinIndex) && { jq_.joinEntries_.emplace_back(op_, cond, std::move(index), std::move(joinIndex)); op_ = OpAnd; return std::move(*this); } +[[nodiscard]] inline auto Query::Join(JoinType joinType, Query &&q) & { + Join({joinType, std::move(q)}); + return OnHelper{*this, joinQueries_.back()}; +} + +[[nodiscard]] inline auto Query::Join(JoinType joinType, const Query &q) & { + Join({joinType, q}); + return OnHelper{*this, joinQueries_.back()}; +} + +[[nodiscard]] inline auto Query::Join(JoinType joinType, Query &&q) && { + Join({joinType, std::move(q)}); + return OnHelperR{std::move(*this), joinQueries_.back()}; +} + +[[nodiscard]] inline auto Query::Join(JoinType joinType, const Query &q) && { + Join({joinType, q}); + return OnHelperR{std::move(*this), joinQueries_.back()}; +} + } // namespace reindexer diff --git a/cpp_src/core/query/queryentry.cc b/cpp_src/core/query/queryentry.cc index d7148dc49..74b62dfab 100644 --- a/cpp_src/core/query/queryentry.cc +++ b/cpp_src/core/query/queryentry.cc @@ -110,9 +110,9 @@ bool QueryEntry::operator==(const QueryEntry &other) const noexcept { values_.RelaxCompare(other.values_) == 0; } -template -void QueryEntry::verify(CondType cond, const VariantArray &values) { - if constexpr (flags & kIgnoreEmptyValues) { +template +void VerifyQueryEntryValues(CondType cond, const VariantArray &values) { + if constexpr (flags & VerifyQueryEntryFlags::ignoreEmptyValues) { if (values.empty()) { return; } @@ -154,8 +154,8 @@ void QueryEntry::verify(CondType cond, const VariantArray &values) { break; } } -template void QueryEntry::verify<0u>(CondType, const VariantArray &); -template void QueryEntry::verify(CondType, const VariantArray &); +template void VerifyQueryEntryValues(CondType, const VariantArray &); +template void VerifyQueryEntryValues(CondType, const VariantArray &); std::string QueryEntry::Dump() const { WrSerializer ser; @@ -267,14 +267,55 @@ std::string BetweenFieldsQueryEntry::Dump() const { return std::string{ser.Slice()}; } -void QueryEntries::serialize(const_iterator it, const_iterator to, WrSerializer &ser) { +void QueryEntries::serialize(CondType cond, const VariantArray &values, WrSerializer &ser) { + ser.PutVarUint(cond); + if (cond == CondDWithin) { + assertrx_throw(values.size() == 2); + ser.PutVarUint(3); + if (values[0].Type().Is()) { + const Point point = static_cast(values[0]); + ser.PutDouble(point.X()); + ser.PutDouble(point.Y()); + ser.PutVariant(values[1]); + } else { + const Point point = static_cast(values[1]); + ser.PutDouble(point.X()); + ser.PutDouble(point.Y()); + ser.PutVariant(values[0]); + } + } else { + ser.PutVarUint(values.size()); + for (auto &kv : values) ser.PutVariant(kv); + } +} + +void QueryEntries::serialize(const_iterator it, const_iterator to, WrSerializer &ser, const std::vector &subQueries) { for (; it != to; ++it) { const OpType op = it->operation; it->InvokeAppropriate( - [&ser, op, &it](const QueryEntriesBracket &) { + [&ser, op, &subQueries](const SubQueryEntry &sqe) { + ser.PutVarUint(QuerySubQueryCondition); + ser.PutVarUint(op); + { + const auto sizePosSaver = ser.StartVString(); + subQueries.at(sqe.QueryIndex()).Serialize(ser); + } + serialize(sqe.Condition(), sqe.Values(), ser); + }, + [&ser, op, &subQueries](const SubQueryFieldEntry &sqe) { + ser.PutVarUint(QueryFieldSubQueryCondition); + ser.PutVarUint(op); + ser.PutVString(sqe.FieldName()); + ser.PutVarUint(sqe.Condition()); + { + const auto sizePosSaver = ser.StartVString(); + subQueries.at(sqe.QueryIndex()).Serialize(ser); + } + }, + [&](const QueryEntriesBracket &) { ser.PutVarUint(QueryOpenBracket); ser.PutVarUint(op); - serialize(it.cbegin(), it.cend(), ser); + serialize(it.cbegin(), it.cend(), ser, subQueries); ser.PutVarUint(QueryCloseBracket); }, [&ser, op](const QueryEntry &entry) { @@ -282,28 +323,7 @@ void QueryEntries::serialize(const_iterator it, const_iterator to, WrSerializer ser.PutVString(entry.FieldName()); if (entry.Distinct()) return; ser.PutVarUint(op); - ser.PutVarUint(entry.Condition()); - if (entry.Condition() == CondDWithin) { - if (entry.Values().size() != 2) { - throw Error(errLogic, "Condition DWithin must have exact 2 value, but %d values was provided", - entry.Values().size()); - } - ser.PutVarUint(3); - if (entry.Values()[0].Type().Is()) { - const Point point = static_cast(entry.Values()[0]); - ser.PutDouble(point.X()); - ser.PutDouble(point.Y()); - ser.PutVariant(entry.Values()[1]); - } else { - const Point point = static_cast(entry.Values()[1]); - ser.PutDouble(point.X()); - ser.PutDouble(point.Y()); - ser.PutVariant(entry.Values()[0]); - } - } else { - ser.PutVarUint(entry.Values().size()); - for (auto &kv : entry.Values()) ser.PutVariant(kv); - } + serialize(entry.Condition(), entry.Values(), ser); }, [&ser, op](const JoinQueryEntry &jqe) { ser.PutVarUint(QueryJoinCondition); @@ -320,6 +340,10 @@ void QueryEntries::serialize(const_iterator it, const_iterator to, WrSerializer [&ser, op](const AlwaysFalse &) { ser.PutVarUint(QueryAlwaysFalseCondition); ser.PutVarUint(op); + }, + [&ser, op](const AlwaysTrue &) { + ser.PutVarUint(QueryAlwaysTrueCondition); + ser.PutVarUint(op); }); } } @@ -354,10 +378,19 @@ bool QueryEntries::checkIfSatisfyConditions(const_iterator begin, const_iterator break; } const bool lastResult = it->InvokeAppropriate( + [](const SubQueryEntry &) -> bool { + assertrx_throw(0); + abort(); + }, + [](const SubQueryFieldEntry &) -> bool { + assertrx_throw(0); + abort(); + }, [&it, &pl](const QueryEntriesBracket &) { return checkIfSatisfyConditions(it.cbegin(), it.cend(), pl); }, [&pl](const QueryEntry &qe) { return checkIfSatisfyCondition(qe, pl); }, [&pl](const BetweenFieldsQueryEntry &qe) { return checkIfSatisfyCondition(qe, pl); }, - [](const JoinQueryEntry &) -> bool { abort(); }, [](const AlwaysFalse &) { return false; }); + [](const JoinQueryEntry &) -> bool { abort(); }, [](const AlwaysFalse &) noexcept { return false; }, + [](const AlwaysTrue &) noexcept { return true; }); result = (lastResult != (it->operation == OpNot)); } return result; @@ -366,7 +399,7 @@ bool QueryEntries::checkIfSatisfyConditions(const_iterator begin, const_iterator bool QueryEntries::checkIfSatisfyCondition(const QueryEntry &qEntry, const ConstPayload &pl) { VariantArray values; pl.GetByFieldsSet(qEntry.Fields(), values, qEntry.FieldType(), qEntry.CompositeFieldsTypes()); - return checkIfSatisfyCondition(values, qEntry.Condition(), qEntry.Values()); + return CheckIfSatisfyCondition(values, qEntry.Condition(), qEntry.Values()); } bool QueryEntries::checkIfSatisfyCondition(const BetweenFieldsQueryEntry &qEntry, const ConstPayload &pl) { @@ -374,10 +407,10 @@ bool QueryEntries::checkIfSatisfyCondition(const BetweenFieldsQueryEntry &qEntry pl.GetByFieldsSet(qEntry.LeftFields(), lValues, qEntry.LeftFieldType(), qEntry.LeftCompositeFieldsTypes()); VariantArray rValues; pl.GetByFieldsSet(qEntry.RightFields(), rValues, qEntry.RightFieldType(), qEntry.RightCompositeFieldsTypes()); - return checkIfSatisfyCondition(lValues, qEntry.Condition(), rValues); + return CheckIfSatisfyCondition(lValues, qEntry.Condition(), rValues); } -bool QueryEntries::checkIfSatisfyCondition(const VariantArray &lValues, CondType condition, const VariantArray &rValues) { +bool QueryEntries::CheckIfSatisfyCondition(const VariantArray &lValues, CondType condition, const VariantArray &rValues) { switch (condition) { case CondType::CondAny: return !lValues.empty(); @@ -402,29 +435,33 @@ bool QueryEntries::checkIfSatisfyCondition(const VariantArray &lValues, CondType } return true; case CondType::CondLt: - case CondType::CondLe: { - auto lit = lValues.cbegin(); - auto rit = rValues.cbegin(); - for (; lit != lValues.cend() && rit != rValues.cend(); ++lit, ++rit) { - const int res = lit->RelaxCompare(*rit); - if (res < 0) return true; - if (res > 0) return false; + for (const auto &lhs : lValues) { + for (const auto &rhs : rValues) { + if (lhs.RelaxCompare(rhs) < 0) return true; + } + } + return false; + case CondType::CondLe: + for (const auto &lhs : lValues) { + for (const auto &rhs : rValues) { + if (lhs.RelaxCompare(rhs) <= 0) return true; + } } - if (lit == lValues.cend() && ((rit == rValues.cend()) == (condition == CondType::CondLe))) return true; return false; - } case CondType::CondGt: - case CondType::CondGe: { - auto lit = lValues.cbegin(); - auto rit = rValues.cbegin(); - for (; lit != lValues.cend() && rit != rValues.cend(); ++lit, ++rit) { - const int res = lit->RelaxCompare(*rit); - if (res > 0) return true; - if (res < 0) return false; + for (const auto &lhs : lValues) { + for (const auto &rhs : rValues) { + if (lhs.RelaxCompare(rhs) > 0) return true; + } + } + return false; + case CondType::CondGe: + for (const auto &lhs : lValues) { + for (const auto &rhs : rValues) { + if (lhs.RelaxCompare(rhs) >= 0) return true; + } } - if (rit == rValues.cend() && ((lit == lValues.cend()) == (condition == CondType::CondGe))) return true; return false; - } case CondType::CondRange: for (const auto &v : lValues) { if (v.RelaxCompare(rValues[0]) < 0 || v.RelaxCompare(rValues[1]) > 0) return false; @@ -482,8 +519,27 @@ void QueryEntries::dumpEqualPositions(size_t level, WrSerializer &ser, const Equ } } +std::string SubQueryEntry::Dump(const std::vector &subQueries) const { + std::stringstream ss; + ss << '(' << subQueries.at(QueryIndex()).GetSQL() << ") " << Condition() << ' '; + if (Values().size() > 1) ss << '['; + for (size_t i = 0, s = Values().size(); i != s; ++i) { + if (i != 0) ss << ','; + ss << '\'' << Values()[i].As() << '\''; + } + if (Values().size() > 1) ss << ']'; + return ss.str(); +} + +std::string SubQueryFieldEntry::Dump(const std::vector &subQueries) const { + std::stringstream ss; + ss << FieldName() << ' ' << Condition() << " (" << subQueries.at(QueryIndex()).GetSQL() << ')'; + return ss.str(); +} + template -void QueryEntries::dump(size_t level, const_iterator begin, const_iterator end, const std::vector &joinedSelectors, WrSerializer &ser) { +void QueryEntries::dump(size_t level, const_iterator begin, const_iterator end, const std::vector &joinedSelectors, + const std::vector &subQueries, WrSerializer &ser) { for (const_iterator it = begin; it != end; ++it) { for (size_t i = 0; i < level; ++i) { ser << " "; @@ -491,20 +547,22 @@ void QueryEntries::dump(size_t level, const_iterator begin, const_iterator end, if (it != begin || it->operation != OpAnd) { ser << it->operation << ' '; } - it->InvokeAppropriate( - [&](const QueryEntriesBracket &b) { - ser << "(\n"; - dump(level + 1, it.cbegin(), it.cend(), joinedSelectors, ser); - dumpEqualPositions(level + 1, ser, b.equalPositions); - for (size_t i = 0; i < level; ++i) { - ser << " "; - } - ser << ")\n"; - }, - [&ser](const QueryEntry &qe) { ser << qe.Dump() << '\n'; }, - [&joinedSelectors, &ser](const JoinQueryEntry &jqe) { ser << jqe.Dump(joinedSelectors) << '\n'; }, - [&ser](const BetweenFieldsQueryEntry &qe) { ser << qe.Dump() << '\n'; }, - [&ser](const AlwaysFalse &) { ser << "AlwaysFalse" << 'n'; }); + it->InvokeAppropriate([&ser, subQueries](const SubQueryEntry &sqe) { ser << sqe.Dump(subQueries); }, + [&ser, subQueries](const SubQueryFieldEntry &sqe) { ser << sqe.Dump(subQueries); }, + [&](const QueryEntriesBracket &b) { + ser << "(\n"; + dump(level + 1, it.cbegin(), it.cend(), joinedSelectors, ser); + dumpEqualPositions(level + 1, ser, b.equalPositions); + for (size_t i = 0; i < level; ++i) { + ser << " "; + } + ser << ")\n"; + }, + [&ser](const QueryEntry &qe) { ser << qe.Dump() << '\n'; }, + [&joinedSelectors, &ser](const JoinQueryEntry &jqe) { ser << jqe.Dump(joinedSelectors) << '\n'; }, + [&ser](const BetweenFieldsQueryEntry &qe) { ser << qe.Dump() << '\n'; }, + [&ser](const AlwaysFalse &) { ser << "AlwaysFalse" << 'n'; }, + [&ser](const AlwaysTrue &) { ser << "AlwaysTrue" << 'n'; }); } } diff --git a/cpp_src/core/query/queryentry.h b/cpp_src/core/query/queryentry.h index 6d00faf35..84ef66a88 100644 --- a/cpp_src/core/query/queryentry.h +++ b/cpp_src/core/query/queryentry.h @@ -48,11 +48,11 @@ class QueryField { [[nodiscard]] int IndexNo() const noexcept { return idxNo_; } [[nodiscard]] bool IsFieldIndexed() const noexcept { return idxNo_ >= 0; } [[nodiscard]] bool FieldsHaveBeenSet() const noexcept { return idxNo_ != IndexValueType::NotSet; } - [[nodiscard]] const FieldsSet &Fields() const &noexcept { return fieldsSet_; } - [[nodiscard]] const std::string &FieldName() const &noexcept { return fieldName_; } + [[nodiscard]] const FieldsSet &Fields() const & noexcept { return fieldsSet_; } + [[nodiscard]] const std::string &FieldName() const & noexcept { return fieldName_; } [[nodiscard]] KeyValueType FieldType() const noexcept { return fieldType_; } [[nodiscard]] KeyValueType SelectType() const noexcept { return selectType_; } - [[nodiscard]] const std::vector &CompositeFieldsTypes() const &noexcept { return compositeFieldsTypes_; } + [[nodiscard]] const std::vector &CompositeFieldsTypes() const & noexcept { return compositeFieldsTypes_; } [[nodiscard]] bool HaveEmptyField() const noexcept; void SetField(FieldsSet &&fields) &; void SetIndexData(int idxNo, FieldsSet &&fields, KeyValueType fieldType, KeyValueType selectType, @@ -72,9 +72,18 @@ class QueryField { std::vector compositeFieldsTypes_; }; -class QueryEntry : private QueryField { - static constexpr unsigned kIgnoreEmptyValues = 1u; +enum class VerifyQueryEntryFlags : unsigned { null = 0u, ignoreEmptyValues = 1u }; +[[nodiscard]] RX_ALWAYS_INLINE constexpr bool operator&(VerifyQueryEntryFlags lhs, VerifyQueryEntryFlags rhs) noexcept { + using UnderlyingType = std::underlying_type_t; + return static_cast(lhs) & static_cast(rhs); +} + +template +void VerifyQueryEntryValues(CondType, const VariantArray &); +extern template void VerifyQueryEntryValues(CondType, const VariantArray &); +extern template void VerifyQueryEntryValues(CondType, const VariantArray &); +class QueryEntry : private QueryField { public: struct DistinctTag {}; struct IgnoreEmptyValues {}; @@ -98,9 +107,9 @@ class QueryEntry : private QueryField { verifyIgnoringEmptyValues(); } [[nodiscard]] CondType Condition() const noexcept { return condition_; } - [[nodiscard]] const VariantArray &Values() const &noexcept { return values_; } - [[nodiscard]] VariantArray &&Values() &&noexcept { return std::move(values_); } - [[nodiscard]] auto UpdatableValues(IgnoreEmptyValues) &noexcept { + [[nodiscard]] const VariantArray &Values() const & noexcept { return values_; } + [[nodiscard]] VariantArray &&Values() && noexcept { return std::move(values_); } + [[nodiscard]] auto UpdatableValues(IgnoreEmptyValues) & noexcept { return VerifyingUpdater{*this}; } [[nodiscard]] bool Distinct() const noexcept { return distinct_; } @@ -117,13 +126,13 @@ class QueryEntry : private QueryField { using QueryField::SetIndexData; using QueryField::HaveEmptyField; void SetCondAndValues(CondType cond, VariantArray &&values) { - verify(cond, values); + VerifyQueryEntryValues(cond, values); condition_ = cond; values_ = std::move(values); } - const QueryField &FieldData() const &noexcept { return static_cast(*this); } - QueryField &FieldData() &noexcept { return static_cast(*this); } + const QueryField &FieldData() const & noexcept { return static_cast(*this); } + QueryField &FieldData() & noexcept { return static_cast(*this); } void ConvertValuesToFieldType() & { for (Variant &v : values_) { v.convert(SelectType()); @@ -137,7 +146,7 @@ class QueryEntry : private QueryField { v.convert(SelectType(), &pt, &Fields()); } } - void Verify() const { verify(condition_, values_); } + void Verify() const { VerifyQueryEntryValues(condition_, values_); } [[nodiscard]] bool operator==(const QueryEntry &) const noexcept; [[nodiscard]] bool operator!=(const QueryEntry &other) const noexcept { return !operator==(other); } @@ -149,16 +158,12 @@ class QueryEntry : private QueryField { auto FieldData() const && = delete; private: - template - static void verify(CondType, const VariantArray &); - void verifyIgnoringEmptyValues() const { verify(condition_, values_); } + void verifyIgnoringEmptyValues() const { VerifyQueryEntryValues(condition_, values_); } VariantArray values_; CondType condition_; bool distinct_{false}; }; -extern template void QueryEntry::verify<0u>(CondType, const VariantArray &); -extern template void QueryEntry::verify(CondType, const VariantArray &); class BetweenFieldsQueryEntry { public: @@ -176,20 +181,20 @@ class BetweenFieldsQueryEntry { [[nodiscard]] CondType Condition() const noexcept { return condition_; } [[nodiscard]] int LeftIdxNo() const noexcept { return leftField_.IndexNo(); } [[nodiscard]] int RightIdxNo() const noexcept { return rightField_.IndexNo(); } - [[nodiscard]] const std::string &LeftFieldName() const &noexcept { return leftField_.FieldName(); } - [[nodiscard]] const std::string &RightFieldName() const &noexcept { return rightField_.FieldName(); } - [[nodiscard]] const FieldsSet &LeftFields() const &noexcept { return leftField_.Fields(); } - [[nodiscard]] const FieldsSet &RightFields() const &noexcept { return rightField_.Fields(); } + [[nodiscard]] const std::string &LeftFieldName() const & noexcept { return leftField_.FieldName(); } + [[nodiscard]] const std::string &RightFieldName() const & noexcept { return rightField_.FieldName(); } + [[nodiscard]] const FieldsSet &LeftFields() const & noexcept { return leftField_.Fields(); } + [[nodiscard]] const FieldsSet &RightFields() const & noexcept { return rightField_.Fields(); } [[nodiscard]] KeyValueType LeftFieldType() const noexcept { return leftField_.FieldType(); } [[nodiscard]] KeyValueType RightFieldType() const noexcept { return rightField_.FieldType(); } - [[nodiscard]] const std::vector &LeftCompositeFieldsTypes() const &noexcept { return leftField_.CompositeFieldsTypes(); } - [[nodiscard]] const std::vector &RightCompositeFieldsTypes() const &noexcept { + [[nodiscard]] const std::vector &LeftCompositeFieldsTypes() const & noexcept { return leftField_.CompositeFieldsTypes(); } + [[nodiscard]] const std::vector &RightCompositeFieldsTypes() const & noexcept { return rightField_.CompositeFieldsTypes(); } - [[nodiscard]] const QueryField &LeftFieldData() const &noexcept { return leftField_; } - [[nodiscard]] QueryField &LeftFieldData() &noexcept { return leftField_; } - [[nodiscard]] const QueryField &RightFieldData() const &noexcept { return rightField_; } - [[nodiscard]] QueryField &RightFieldData() &noexcept { return rightField_; } + [[nodiscard]] const QueryField &LeftFieldData() const & noexcept { return leftField_; } + [[nodiscard]] QueryField &LeftFieldData() & noexcept { return leftField_; } + [[nodiscard]] const QueryField &RightFieldData() const & noexcept { return rightField_; } + [[nodiscard]] QueryField &RightFieldData() & noexcept { return rightField_; } [[nodiscard]] bool FieldsHaveBeenSet() const noexcept { return leftField_.FieldsHaveBeenSet() && rightField_.FieldsHaveBeenSet(); } [[nodiscard]] bool IsLeftFieldIndexed() const noexcept { return leftField_.IsFieldIndexed(); } [[nodiscard]] bool IsRightFieldIndexed() const noexcept { return rightField_.IsFieldIndexed(); } @@ -212,6 +217,8 @@ class BetweenFieldsQueryEntry { struct AlwaysFalse {}; constexpr bool operator==(AlwaysFalse, AlwaysFalse) noexcept { return true; } +struct AlwaysTrue {}; +constexpr bool operator==(AlwaysTrue, AlwaysTrue) noexcept { return true; } class JsonBuilder; @@ -226,9 +233,60 @@ struct QueryEntriesBracket : public Bracket { EqualPositions_t equalPositions; }; -class QueryEntries - : public ExpressionTree { - using Base = ExpressionTree; +class SubQueryEntry { +public: + SubQueryEntry(CondType cond, size_t qIdx, VariantArray &&values) : condition_{cond}, queryIndex_{qIdx}, values_{std::move(values)} { + VerifyQueryEntryValues(condition_, values_); + } + [[nodiscard]] CondType Condition() const noexcept { return condition_; } + [[nodiscard]] size_t QueryIndex() const noexcept { return queryIndex_; } + [[nodiscard]] const VariantArray &Values() const & noexcept { return values_; } + [[nodiscard]] bool operator==(const SubQueryEntry &other) const noexcept { + return condition_ == other.condition_ && queryIndex_ == other.queryIndex_; + } + [[nodiscard]] bool operator!=(const SubQueryEntry &other) const noexcept { return !operator==(other); } + [[nodiscard]] std::string Dump(const std::vector &subQueries) const; + + auto Values() const && = delete; + +private: + CondType condition_; + // index of Query in Query::subQueries_ + size_t queryIndex_; + VariantArray values_; +}; + +class SubQueryFieldEntry { +public: + template + SubQueryFieldEntry(Str &&field, CondType cond, size_t qIdx) : field_{std::forward(field)}, condition_{cond}, queryIndex_{qIdx} { + if (cond == CondAny || cond == CondEmpty) { + throw Error{errQueryExec, "Condition %s with field and subquery", cond == CondAny ? "Any" : "Empty"}; + } + } + [[nodiscard]] const std::string &FieldName() const & noexcept { return field_; } + [[nodiscard]] std::string &&FieldName() && noexcept { return std::move(field_); } + [[nodiscard]] CondType Condition() const noexcept { return condition_; } + [[nodiscard]] size_t QueryIndex() const noexcept { return queryIndex_; } + [[nodiscard]] bool operator==(const SubQueryFieldEntry &other) const noexcept { + return field_ == other.field_ && condition_ == other.condition_ && queryIndex_ == other.queryIndex_; + } + [[nodiscard]] bool operator!=(const SubQueryFieldEntry &other) const noexcept { return !operator==(other); } + [[nodiscard]] std::string Dump(const std::vector &subQueries) const; + + auto FieldName() const && = delete; + +private: + std::string field_; + CondType condition_; + // index of Query in Query::subQueries_ + size_t queryIndex_; +}; + +class QueryEntries : public ExpressionTree { + using Base = ExpressionTree; QueryEntries(Base &&b) : Base{std::move(b)} {} public: @@ -236,16 +294,16 @@ class QueryEntries QueryEntries(QueryEntries &&) = default; QueryEntries(const QueryEntries &) = default; QueryEntries &operator=(QueryEntries &&) = default; - QueryEntries MakeLazyCopy() & { return {makeLazyCopy()}; } void ToDsl(const Query &parentQuery, JsonBuilder &builder) const { return toDsl(cbegin(), cend(), parentQuery, builder); } void WriteSQLWhere(const Query &parentQuery, WrSerializer &, bool stripArgs) const; - void Serialize(WrSerializer &ser) const { serialize(cbegin(), cend(), ser); } + void Serialize(WrSerializer &ser, const std::vector &subQueries) const { serialize(cbegin(), cend(), ser, subQueries); } bool CheckIfSatisfyConditions(const ConstPayload &pl) const { return checkIfSatisfyConditions(cbegin(), cend(), pl); } + static bool CheckIfSatisfyCondition(const VariantArray &lValues, CondType, const VariantArray &rValues); template - std::string Dump(const std::vector &joinedSelectors) const { + std::string Dump(const std::vector &joinedSelectors, const std::vector &subQueries) const { WrSerializer ser; - dump(0, cbegin(), cend(), joinedSelectors, ser); + dump(0, cbegin(), cend(), joinedSelectors, subQueries, ser); dumpEqualPositions(0, ser, equalPositions); return std::string{ser.Slice()}; } @@ -255,16 +313,17 @@ class QueryEntries private: static void toDsl(const_iterator it, const_iterator to, const Query &parentQuery, JsonBuilder &); static void writeSQL(const Query &parentQuery, const_iterator from, const_iterator to, WrSerializer &, bool stripArgs); - static void serialize(const_iterator it, const_iterator to, WrSerializer &); + static void serialize(const_iterator it, const_iterator to, WrSerializer &, const std::vector &subQueries); + static void serialize(CondType, const VariantArray &values, WrSerializer &); static bool checkIfSatisfyConditions(const_iterator begin, const_iterator end, const ConstPayload &); static bool checkIfSatisfyCondition(const QueryEntry &, const ConstPayload &); static bool checkIfSatisfyCondition(const BetweenFieldsQueryEntry &, const ConstPayload &); - static bool checkIfSatisfyCondition(const VariantArray &lValues, CondType, const VariantArray &rValues); protected: static void dumpEqualPositions(size_t level, WrSerializer &, const EqualPositions_t &); template - static void dump(size_t level, const_iterator begin, const_iterator end, const std::vector &joinedSelectors, WrSerializer &); + static void dump(size_t level, const_iterator begin, const_iterator end, const std::vector &joinedSelectors, + const std::vector &subQueries, WrSerializer &); }; class UpdateEntry { @@ -303,23 +362,23 @@ class QueryJoinEntry { [[nodiscard]] bool IsRightFieldIndexed() const noexcept { return rightField_.IsFieldIndexed(); } [[nodiscard]] int LeftIdxNo() const noexcept { return leftField_.IndexNo(); } [[nodiscard]] int RightIdxNo() const noexcept { return rightField_.IndexNo(); } - [[nodiscard]] const FieldsSet &LeftFields() const &noexcept { return leftField_.Fields(); } - [[nodiscard]] const FieldsSet &RightFields() const &noexcept { return rightField_.Fields(); } + [[nodiscard]] const FieldsSet &LeftFields() const & noexcept { return leftField_.Fields(); } + [[nodiscard]] const FieldsSet &RightFields() const & noexcept { return rightField_.Fields(); } [[nodiscard]] KeyValueType LeftFieldType() const noexcept { return leftField_.FieldType(); } [[nodiscard]] KeyValueType RightFieldType() const noexcept { return rightField_.FieldType(); } - [[nodiscard]] const std::vector &LeftCompositeFieldsTypes() const &noexcept { return leftField_.CompositeFieldsTypes(); } - [[nodiscard]] const std::vector &RightCompositeFieldsTypes() const &noexcept { + [[nodiscard]] const std::vector &LeftCompositeFieldsTypes() const & noexcept { return leftField_.CompositeFieldsTypes(); } + [[nodiscard]] const std::vector &RightCompositeFieldsTypes() const & noexcept { return rightField_.CompositeFieldsTypes(); } [[nodiscard]] OpType Operation() const noexcept { return op_; } [[nodiscard]] CondType Condition() const noexcept { return condition_; } - [[nodiscard]] const std::string &LeftFieldName() const &noexcept { return leftField_.FieldName(); } - [[nodiscard]] const std::string &RightFieldName() const &noexcept { return rightField_.FieldName(); } + [[nodiscard]] const std::string &LeftFieldName() const & noexcept { return leftField_.FieldName(); } + [[nodiscard]] const std::string &RightFieldName() const & noexcept { return rightField_.FieldName(); } [[nodiscard]] bool ReverseNamespacesOrder() const noexcept { return reverseNamespacesOrder_; } - [[nodiscard]] const QueryField &LeftFieldData() const &noexcept { return leftField_; } - [[nodiscard]] QueryField &LeftFieldData() &noexcept { return leftField_; } - [[nodiscard]] const QueryField &RightFieldData() const &noexcept { return rightField_; } - [[nodiscard]] QueryField &RightFieldData() &noexcept { return rightField_; } + [[nodiscard]] const QueryField &LeftFieldData() const & noexcept { return leftField_; } + [[nodiscard]] QueryField &LeftFieldData() & noexcept { return leftField_; } + [[nodiscard]] const QueryField &RightFieldData() const & noexcept { return rightField_; } + [[nodiscard]] QueryField &RightFieldData() & noexcept { return rightField_; } void SetLeftIndexData(int idxNo, FieldsSet &&fields, KeyValueType fieldType, KeyValueType selectType, std::vector &&compositeFieldsTypes) & { leftField_.SetIndexData(idxNo, std::move(fields), fieldType, selectType, std::move(compositeFieldsTypes)); diff --git a/cpp_src/core/query/sql/sqlencoder.cc b/cpp_src/core/query/sql/sqlencoder.cc index 020ffea20..6a745bf1c 100644 --- a/cpp_src/core/query/sql/sqlencoder.cc +++ b/cpp_src/core/query/sql/sqlencoder.cc @@ -4,19 +4,21 @@ #include "core/keyvalue/p_string.h" #include "core/queryresults/aggregationresult.h" #include "core/type_consts_helpers.h" +#include "tools/logger.h" #include "tools/serializer.h" -namespace reindexer { +enum class NeedQuote : bool { No = false, Yes = true }; -static void indexToSql(const std::string &index, WrSerializer &ser) { - if (index.find('+') == std::string::npos) { +template +static void indexToSql(std::string_view index, reindexer::WrSerializer &ser) { + if (needQuote == NeedQuote::No || index.find('+') == std::string::npos) { ser << index; } else { ser << '"' << index << '"'; } } -static WrSerializer &stringToSql(std::string_view str, WrSerializer &ser) { +static reindexer::WrSerializer &stringToSql(std::string_view str, reindexer::WrSerializer &ser) { ser << '\''; for (auto c : str) { switch (c) { @@ -48,11 +50,14 @@ static WrSerializer &stringToSql(std::string_view str, WrSerializer &ser) { ser << '\''; return ser; } + +namespace reindexer { + void SQLEncoder::DumpSingleJoinQuery(size_t idx, WrSerializer &ser, bool stripArgs) const { - assertrx(idx < query_.joinQueries_.size()); - const auto &jq = query_.joinQueries_[idx]; + assertrx(idx < query_.GetJoinQueries().size()); + const auto &jq = query_.GetJoinQueries()[idx]; ser << ' ' << jq.joinType; - if (jq.entries.Empty() && !jq.HasLimit() && jq.sortingEntries_.empty()) { + if (jq.Entries().Empty() && !jq.HasLimit() && jq.sortingEntries_.empty()) { ser << ' ' << jq.NsName() << " ON "; } else { ser << " ("; @@ -75,15 +80,15 @@ void SQLEncoder::DumpSingleJoinQuery(size_t idx, WrSerializer &ser, bool stripAr } void SQLEncoder::dumpJoined(WrSerializer &ser, bool stripArgs) const { - for (size_t i = 0; i < query_.joinQueries_.size(); ++i) { - if (query_.joinQueries_[i].joinType == JoinType::LeftJoin) { + for (size_t i = 0; i < query_.GetJoinQueries().size(); ++i) { + if (query_.GetJoinQueries()[i].joinType == JoinType::LeftJoin) { DumpSingleJoinQuery(i, ser, stripArgs); } } } void SQLEncoder::dumpMerged(WrSerializer &ser, bool stripArgs) const { - for (auto &me : query_.mergeQueries_) { + for (auto &me : query_.GetMergeQueries()) { ser << ' ' << me.joinType << "( "; me.GetSQL(ser, stripArgs); ser << ')'; @@ -167,16 +172,16 @@ WrSerializer &SQLEncoder::GetSQL(WrSerializer &ser, bool stripArgs) const { assertrx(query_.aggregations_[0].Fields().size() == 1); distinctIndex = query_.aggregations_[0].Fields()[0]; } - if (query_.selectFilter_.empty()) { - if (query_.Limit() != 0 || query_.CalcTotal() == ModeNoTotal) { + if (query_.SelectFilters().empty()) { + if (query_.Limit() != 0 || !query_.HasCalcTotal()) { if (needComma) ser << ", "; ser << '*'; - if (query_.CalcTotal() != ModeNoTotal) { + if (query_.HasCalcTotal()) { needComma = true; } } } else { - for (const auto &filter : query_.selectFilter_) { + for (const auto &filter : query_.SelectFilters()) { if (filter == distinctIndex) continue; if (needComma) { ser << ", "; @@ -187,7 +192,7 @@ WrSerializer &SQLEncoder::GetSQL(WrSerializer &ser, bool stripArgs) const { } } } - if (query_.CalcTotal() != ModeNoTotal) { + if (query_.HasCalcTotal()) { if (needComma) ser << ", "; if (query_.CalcTotal() == ModeAccurateTotal) ser << "COUNT(*)"; if (query_.CalcTotal() == ModeCachedTotal) ser << "COUNT_CACHED(*)"; @@ -254,6 +259,61 @@ WrSerializer &SQLEncoder::GetSQL(WrSerializer &ser, bool stripArgs) const { static const char *opNames[] = {"-", "OR", "AND", "AND NOT"}; +template +static void dumpCondWithValues(WrSerializer &ser, std::string_view fieldName, CondType cond, const VariantArray &values, bool stripArgs) { + switch (cond) { + case CondDWithin: + ser << "ST_DWithin("; + indexToSql(fieldName, ser); + if (stripArgs) { + ser << ", ?, ?)"; + } else { + assertrx(values.size() == 2); + Point point; + double distance; + if (values[0].Type().Is()) { + point = static_cast(values[0]); + distance = values[1].As(); + } else { + point = static_cast(values[1]); + distance = values[0].As(); + } + ser << ", ST_GeomFromText('POINT(" << point.X() << ' ' << point.Y() << ")'), " << distance << ')'; + } + break; + case CondAny: + case CondEmpty: + indexToSql(fieldName, ser); + ser << ' ' << cond; + break; + case CondGt: + case CondGe: + case CondLt: + case CondLe: + case CondEq: + case CondSet: + case CondAllSet: + case CondRange: + case CondLike: + indexToSql(fieldName, ser); + ser << ' ' << cond << ' '; + if (stripArgs) { + ser << '?'; + } else { + if (values.size() != 1) ser << '('; + for (auto &v : values) { + if (&v != &values[0]) ser << ','; + v.Type().EvaluateOneOf(overloaded{ + [&](KeyValueType::String) { stringToSql(v.As(), ser); }, + [&](KeyValueType::Uuid) { ser << '\'' << v.As() << '\''; }, + [&](OneOf) { ser << v.As(); }}); + } + if (values.size() != 1) ser << ")"; + } + } +} + void SQLEncoder::dumpWhereEntries(QueryEntries::const_iterator from, QueryEntries::const_iterator to, WrSerializer &ser, bool stripArgs) const { int encodedEntries = 0; @@ -265,7 +325,29 @@ void SQLEncoder::dumpWhereEntries(QueryEntries::const_iterator from, QueryEntrie ser << "NOT "; } it->InvokeAppropriate( - Skip{}, + [&ser](const AlwaysTrue &) { + logPrintf(LogTrace, "Not normalized query to dsl"); + ser << "true"; + }, + [&ser](const AlwaysFalse &) { + logPrintf(LogTrace, "Not normalized query to dsl"); + ser << "false"; + }, + [&](const SubQueryEntry &sqe) { + if (encodedEntries) { + ser << opNames[op] << ' '; + } + dumpCondWithValues(ser, '(' + query_.GetSubQuery(sqe.QueryIndex()).GetSQL(stripArgs) + ')', sqe.Condition(), + sqe.Values(), stripArgs); + }, + [&](const SubQueryFieldEntry &sqe) { + if (encodedEntries) { + ser << opNames[op] << ' '; + } + ser << sqe.FieldName() << ' ' << sqe.Condition() << " ("; + SQLEncoder{query_.GetSubQuery(sqe.QueryIndex())}.GetSQL(ser, stripArgs); + ser << ')'; + }, [&](const QueryEntriesBracket &bracket) { if (encodedEntries) { ser << opNames[op] << ' '; @@ -279,66 +361,31 @@ void SQLEncoder::dumpWhereEntries(QueryEntries::const_iterator from, QueryEntrie if (encodedEntries) { ser << opNames[op] << ' '; } - if (entry.Condition() == CondDWithin) { - ser << "ST_DWithin("; - indexToSql(entry.FieldName(), ser); - if (stripArgs) { - ser << ", ?, ?)"; - } else { - assertrx(entry.Values().size() == 2); - Point point; - double distance; - if (entry.Values()[0].Type().Is()) { - point = static_cast(entry.Values()[0]); - distance = entry.Values()[1].As(); - } else { - point = static_cast(entry.Values()[1]); - distance = entry.Values()[0].As(); - } - ser << ", ST_GeomFromText('POINT(" << point.X() << ' ' << point.Y() << ")'), " << distance << ')'; - } - } else { - indexToSql(entry.FieldName(), ser); - ser << ' ' << entry.Condition() << ' '; - if (entry.Condition() == CondEmpty || entry.Condition() == CondAny) { - } else if (stripArgs) { - ser << '?'; - } else { - if (entry.Values().size() != 1) ser << '('; - for (auto &v : entry.Values()) { - if (&v != &entry.Values()[0]) ser << ','; - v.Type().EvaluateOneOf(overloaded{ - [&](KeyValueType::String) { stringToSql(v.As(), ser); }, - [&](KeyValueType::Uuid) { ser << '\'' << v.As() << '\''; }, - [&](OneOf) { - ser << v.As(); - }}); - } - if (entry.Values().size() != 1) ser << ")"; - } - } + dumpCondWithValues(ser, entry.FieldName(), entry.Condition(), entry.Values(), stripArgs); }, [&](const JoinQueryEntry &jqe) { - if (encodedEntries && query_.joinQueries_[jqe.joinIndex].joinType != JoinType::OrInnerJoin) { + if (encodedEntries && query_.GetJoinQueries()[jqe.joinIndex].joinType != JoinType::OrInnerJoin) { ser << opNames[op] << ' '; } SQLEncoder(query_).DumpSingleJoinQuery(jqe.joinIndex, ser, stripArgs); }, - [&ser](const BetweenFieldsQueryEntry &entry) { - indexToSql(entry.LeftFieldName(), ser); + [&](const BetweenFieldsQueryEntry &entry) { + if (encodedEntries) { + ser << opNames[op] << ' '; + } + indexToSql(entry.LeftFieldName(), ser); ser << ' ' << entry.Condition() << ' '; - indexToSql(entry.RightFieldName(), ser); + indexToSql(entry.RightFieldName(), ser); }); ++encodedEntries; } } void SQLEncoder::dumpSQLWhere(WrSerializer &ser, bool stripArgs) const { - if (query_.entries.Empty()) return; + if (query_.Entries().Empty()) return; ser << " WHERE "; - dumpWhereEntries(query_.entries.cbegin(), query_.entries.cend(), ser, stripArgs); - dumpEqualPositions(ser, query_.entries.equalPositions); + dumpWhereEntries(query_.Entries().cbegin(), query_.Entries().cend(), ser, stripArgs); + dumpEqualPositions(ser, query_.Entries().equalPositions); } } // namespace reindexer diff --git a/cpp_src/core/query/sql/sqlparser.cc b/cpp_src/core/query/sql/sqlparser.cc index 1cb96cfd1..fc13f00b3 100644 --- a/cpp_src/core/query/sql/sqlparser.cc +++ b/cpp_src/core/query/sql/sqlparser.cc @@ -14,9 +14,11 @@ namespace reindexer { using namespace std::string_view_literals; -int SQLParser::Parse(std::string_view q) { +Query SQLParser::Parse(std::string_view q) { tokenizer parser(q); - return Parse(parser); + Query query; + SQLParser{query}.Parse(parser); + return query; } bool SQLParser::reachedAutocompleteToken(tokenizer &parser, const token &tok) { @@ -47,7 +49,7 @@ int SQLParser::Parse(tokenizer &parser) { parser.skip_space(); token tok = peekSqlToken(parser, Start); if (tok.text() == "explain"sv) { - query_.explain_ = true; + query_.Explain(true); parser.next_token(); tok = peekSqlToken(parser, StartAfterExplain); } @@ -84,6 +86,7 @@ int SQLParser::selectParse(tokenizer &parser) { // Get filter token tok; bool wasSelectFilter = false; + std::vector selectFilters; while (!parser.end()) { auto nameWithCase = peekSqlToken(parser, SingleSelectFieldSqlToken, false); auto name = parser.next_token(); @@ -168,7 +171,7 @@ int SQLParser::selectParse(tokenizer &parser) { if (!query_.CanAddSelectFilter()) { throw Error(errConflict, kAggregationWithSelectFieldsMsgError); } - query_.selectFilter_.emplace_back(nameWithCase.text()); + selectFilters.emplace_back(nameWithCase.text()); query_.Limit(QueryEntry::kDefaultLimit); wasSelectFilter = true; } else if (name.text() == "*"sv) { @@ -177,11 +180,14 @@ int SQLParser::selectParse(tokenizer &parser) { } query_.Limit(QueryEntry::kDefaultLimit); wasSelectFilter = true; - query_.selectFilter_.clear(); + selectFilters.clear(); } if (tok.text() != ","sv) break; tok = parser.next_token(); } + if (wasSelectFilter) { + query_.Select(std::move(selectFilters)); + } peekSqlToken(parser, FromSqlToken); if (parser.next_token().text() != "from"sv) @@ -228,15 +234,15 @@ int SQLParser::selectParse(tokenizer &parser) { if (parser.next_token().text() != "join") { throw Error(errParseSQL, "Expected JOIN, but found '%s' in query, %s", tok.text(), parser.where()); } - auto jtype = (query_.nextOp_ == OpOr) ? JoinType::OrInnerJoin : JoinType::InnerJoin; - query_.nextOp_ = OpAnd; + auto jtype = (query_.NextOp() == OpOr) ? JoinType::OrInnerJoin : JoinType::InnerJoin; + query_.And(); parseJoin(jtype, parser); } else if (tok.text() == "merge"sv) { parser.next_token(); parseMerge(parser); } else if (tok.text() == "or"sv) { parser.next_token(); - query_.nextOp_ = OpOr; + query_.Or(); } else { break; } @@ -506,7 +512,7 @@ UpdateEntry SQLParser::parseUpdateField(tokenizer &parser) { updateField.Values().MarkArray(); for (;;) { tok = parser.next_token(tokenizer::flags::no_flags); - if (tok.text() == "]") { + if (tok.text() == "]"sv) { if (updateField.Values().empty()) break; throw Error(errParseSQL, "Expected field value, but found ']' in query, %s", parser.where()); } @@ -554,7 +560,7 @@ int SQLParser::updateParse(tokenizer &parser) { if (tok.text() == "set"sv) { parser.next_token(); while (!parser.end()) { - query_.updateFields_.emplace_back(parseUpdateField(parser)); + query_.UpdateField(parseUpdateField(parser)); tok = parser.peek_token(); if (tok.text() != ","sv) break; parser.next_token(); @@ -593,6 +599,89 @@ int SQLParser::truncateParse(tokenizer &parser) { return 0; } +bool isCondition(std::string_view text) noexcept { + return text == "="sv || text == "=="sv || text == "<>"sv || iequals(text, "is"sv) || text == ">"sv || text == ">="sv || text == "<"sv || + text == "<="sv || iequals(text, "in"sv) || iequals(text, "range"sv) || iequals(text, "like"sv) || iequals(text, "allset"sv); +} + +Query SQLParser::parseSubQuery(tokenizer &parser) { + Query subquery; + SQLParser subparser(subquery); + if (ctx_.autocompleteMode) { + subparser.ctx_.suggestionsPos = ctx_.suggestionsPos; + subparser.ctx_.autocompleteMode = true; + } + // skip select + auto tok = parser.next_token(); + nestedSelectParse(subparser, parser); + tok = parser.next_token(); + if (tok.text() != ")"sv) { + throw Error(errParseSQL, "Expected ')', but found %s, %s", tok.text(), parser.where()); + } + return subquery; +} + +template +void SQLParser::parseWhereCondition(tokenizer &parser, T &&firstArg, OpType op) { + // Operator + CondType condition; + auto tok = peekSqlToken(parser, ConditionSqlToken); + if (tok.text() == "<>"sv) { + condition = CondEq; + if (op == OpAnd) + op = OpNot; + else if (op == OpNot) + op = OpAnd; + else { + throw Error(errParseSQL, "<> condition with OR is not supported, %s", parser.where()); + } + } else { + condition = getCondType(tok.text()); + } + parser.next_token(); + + // Value + if (ctx_.autocompleteMode) peekSqlToken(parser, WhereFieldValueSqlToken, false); + tok = parser.next_token(); + if (iequals(tok.text(), "null"sv) || iequals(tok.text(), "empty"sv)) { + query_.NextOp(op).Where(std::forward(firstArg), CondEmpty, VariantArray{}); + } else if (iequals(tok.text(), "not"sv)) { + tok = peekSqlToken(parser, WhereFieldNegateValueSqlToken, false); + if (!iequals(tok.text(), "null"sv) && !iequals(tok.text(), "empty"sv)) { + throw Error(errParseSQL, "Expected NULL, but found '%s' in query, %s", tok.text(), parser.where()); + } + query_.NextOp(op).Where(std::forward(firstArg), CondAny, VariantArray{}); + tok = parser.next_token(false); + } else if (tok.text() == "("sv) { + if constexpr (!std::is_same_v) { + if (iequals(parser.peek_token().text(), "select"sv) && !isCondition(parser.peek_second_token().text())) { + query_.NextOp(op).Where(std::forward(firstArg), condition, parseSubQuery(parser)); + return; + } + } + VariantArray values; + for (;;) { + tok = parser.next_token(); + if (tok.text() == ")"sv && tok.type == TokenSymbol) break; + values.push_back(token2kv(tok, parser, true)); + tok = parser.next_token(); + if (tok.text() == ")"sv) break; + if (tok.text() != ","sv) + throw Error(errParseSQL, "Expected ')' or ',', but found '%s' in query, %s", tok.text(), parser.where()); + } + query_.NextOp(op).Where(std::forward(firstArg), condition, std::move(values)); + } else if (tok.type != TokenName || iequals(tok.text(), "true"sv) || iequals(tok.text(), "false"sv)) { + query_.NextOp(op).Where(std::forward(firstArg), condition, {token2kv(tok, parser, true)}); + } else { + if constexpr (std::is_same_v) { + throw Error(errParseSQL, "Field cannot be after subquery. (text = '%s' location = %s)", tok.text(), parser.where()); + } else { + // Second field + query_.NextOp(op).WhereBetweenFields(std::forward(firstArg), condition, std::string{tok.text()}); + } + } +} + int SQLParser::parseWhere(tokenizer &parser) { token tok; OpType nextOp = OpAnd; @@ -610,15 +699,21 @@ int SQLParser::parseWhere(tokenizer &parser) { tok = peekSqlToken(parser, WhereFieldSqlToken, false); parser.next_token(false); if (tok.text() == "("sv) { - query_.entries.OpenBracket(nextOp); - ++openBracketsCount; - lastBracketPosition = query_.entries.Size(); tok = peekSqlToken(parser, WhereFieldSqlToken, false); - if (iequals(tok.text(), "not"sv)) { - nextOp = OpNot; - parser.next_token(); - } else { + if (iequals(tok.text(), "select"sv) && !isCondition(parser.peek_second_token().text())) { + parseWhereCondition(parser, parseSubQuery(parser), nextOp); nextOp = OpAnd; + } else { + query_.NextOp(nextOp); + query_.OpenBracket(); + ++openBracketsCount; + lastBracketPosition = query_.Entries().Size(); + if (iequals(tok.text(), "not"sv)) { + nextOp = OpNot; + parser.next_token(); + } else { + nextOp = OpAnd; + } } continue; } @@ -644,62 +739,13 @@ int SQLParser::parseWhere(tokenizer &parser) { throw Error(errParseSQL, "Expected JOIN, but found '%s' in query, %s", tok.text(), parser.where()); } auto jtype = nextOp == OpOr ? JoinType::OrInnerJoin : JoinType::InnerJoin; - query_.nextOp_ = OpAnd; + query_.And(); parseJoin(jtype, parser); } else if (iequals(tok.text(), "st_dwithin"sv)) { parseDWithin(parser, nextOp); nextOp = OpAnd; } else { - // Index name - std::string index{tok.text()}; - - // Operator - CondType condition; - tok = peekSqlToken(parser, ConditionSqlToken); - if (tok.text() == "<>"sv) { - condition = CondEq; - if (nextOp == OpAnd) - nextOp = OpNot; - else if (nextOp == OpNot) - nextOp = OpAnd; - else { - throw Error(errParseSQL, "<> condition with OR is not supported, %s", parser.where()); - } - } else { - condition = getCondType(tok.text()); - } - parser.next_token(); - - // Value - if (ctx_.autocompleteMode) peekSqlToken(parser, WhereFieldValueSqlToken, false); - tok = parser.next_token(); - if (iequals(tok.text(), "null"sv) || iequals(tok.text(), "empty"sv)) { - query_.entries.Append(nextOp, QueryEntry{std::move(index), CondEmpty, {}}); - } else if (iequals(tok.text(), "not"sv)) { - tok = peekSqlToken(parser, WhereFieldNegateValueSqlToken, false); - if (!iequals(tok.text(), "null"sv) && !iequals(tok.text(), "empty"sv)) { - throw Error(errParseSQL, "Expected NULL, but found '%s' in query, %s", tok.text(), parser.where()); - } - query_.entries.Append(nextOp, QueryEntry{std::move(index), CondAny, {}}); - tok = parser.next_token(false); - } else if (tok.text() == "("sv) { - VariantArray values; - for (;;) { - tok = parser.next_token(); - if (tok.text() == ")"sv && tok.type == TokenSymbol) break; - values.push_back(token2kv(tok, parser, true)); - tok = parser.next_token(); - if (tok.text() == ")"sv) break; - if (tok.text() != ","sv) - throw Error(errParseSQL, "Expected ')' or ',', but found '%s' in query, %s", tok.text(), parser.where()); - } - query_.entries.Append(nextOp, QueryEntry{std::move(index), condition, std::move(values)}); - } else if (tok.type != TokenName || toLower(tok.text()) == "true" || toLower(tok.text()) == "false") { - query_.entries.Append(nextOp, QueryEntry{std::move(index), condition, {token2kv(tok, parser, true)}}); - // Second field - } else { - query_.entries.Append(nextOp, BetweenFieldsQueryEntry{std::move(index), condition, std::string{tok.text()}}); - } + parseWhereCondition(parser, std::string{tok.text()}, nextOp); nextOp = OpAnd; } } @@ -711,7 +757,7 @@ int SQLParser::parseWhere(tokenizer &parser) { } while (openBracketsCount > 0 && tok.text() == ")"sv) { - query_.entries.CloseBracket(); + query_.CloseBracket(); --openBracketsCount; parser.next_token(); tok = parser.peek_token(); @@ -736,15 +782,15 @@ int SQLParser::parseWhere(tokenizer &parser) { break; } } - for (auto &&eqPos : equalPositions) { + for (auto &eqPos : equalPositions) { if (eqPos.first == 0) { - query_.entries.equalPositions.emplace_back(std::move(eqPos.second)); + query_.SetEqualPositions(std::move(eqPos.second)); } else { - query_.entries.Get(eqPos.first - 1).equalPositions.emplace_back(std::move(eqPos.second)); + query_.SetEqualPositions(eqPos.first - 1, std::move(eqPos.second)); } } - if (query_.entries.Empty()) { + if (query_.Entries().Empty()) { throw Error(errParseSQL, "Expected condition after 'WHERE'"); } @@ -766,8 +812,8 @@ void SQLParser::parseEqualPositions(tokenizer &parser, std::vectorHoldsOrReferTo() && nameWithCase.text() == it->Value().FieldName()) { + for (auto it = query_.Entries().begin_of_current_bracket(); it != query_.Entries().end(); ++it) { + if (it->Is() && nameWithCase.text() == it->Value().FieldName()) { validField = true; break; } @@ -940,11 +986,7 @@ void SQLParser::parseJoin(JoinType type, tokenizer &parser) { jquery.joinType = type; jparser.parseJoinEntries(parser, query_.NsName(), jquery); - if (type != JoinType::LeftJoin) { - query_.entries.Append((type == JoinType::InnerJoin) ? OpAnd : OpOr, JoinQueryEntry(query_.joinQueries_.size())); - } - - query_.joinQueries_.emplace_back(std::move(jquery)); + query_.Join(std::move(jquery)); } void SQLParser::parseMerge(tokenizer &parser) { @@ -971,7 +1013,7 @@ void SQLParser::parseMerge(tokenizer &parser) { } mquery.joinType = JoinType::Merge; - query_.mergeQueries_.emplace_back(std::move(mquery)); + query_.Merge(std::move(mquery)); } std::string SQLParser::parseJoinedFieldName(tokenizer &parser, std::string &name) { @@ -1010,11 +1052,11 @@ void SQLParser::parseJoinEntries(tokenizer &parser, const std::string &mainNs, J while (!parser.end()) { auto tok = peekSqlToken(parser, OpSqlToken); if (tok.text() == "or"sv) { - jquery.nextOp_ = OpOr; + jquery.Or(); parser.next_token(); tok = parser.peek_token(); } else if (tok.text() == "and"sv) { - jquery.nextOp_ = OpAnd; + jquery.And(); parser.next_token(); tok = parser.peek_token(); } @@ -1041,15 +1083,15 @@ void SQLParser::parseJoinEntries(tokenizer &parser, const std::string &mainNs, J } } - jquery.joinEntries_.emplace_back(jquery.nextOp_, condition, std::move(fld1), std::move(fld2), reverseNamespacesOrder); - jquery.nextOp_ = OpAnd; + jquery.joinEntries_.emplace_back(jquery.NextOp(), condition, std::move(fld1), std::move(fld2), reverseNamespacesOrder); + jquery.And(); if (!braces) { return; } } } CondType SQLParser::getCondType(std::string_view cond) { - if (cond == "="sv || cond == "=="sv || cond == "is"sv) { + if (cond == "="sv || cond == "=="sv || iequals(cond, "is"sv)) { return CondEq; } else if (cond == ">"sv) { return CondGt; diff --git a/cpp_src/core/query/sql/sqlparser.h b/cpp_src/core/query/sql/sqlparser.h index 2c1d17047..b7f01f4f7 100644 --- a/cpp_src/core/query/sql/sqlparser.h +++ b/cpp_src/core/query/sql/sqlparser.h @@ -13,16 +13,16 @@ class JoinedQuery; struct SortingEntries; class UpdateEntry; using EqualPosition_t = h_vector; + class SQLParser { public: - explicit SQLParser(Query &q) noexcept : query_(q) {} - /// Parses pure sql select query and initializes Query object data members as a result. /// @param q - sql query. - /// @return always returns 0. - int Parse(std::string_view q); + /// @return parsed query + [[nodiscard]] static Query Parse(std::string_view sql); protected: + explicit SQLParser(Query &q) noexcept : query_(q) {} /// Sql parser context struct SqlParsingCtx { struct SuggestionData { @@ -89,6 +89,8 @@ class SQLParser { /// Parse where entries int parseWhere(tokenizer &parser); + template + void parseWhereCondition(tokenizer &, T &&firstArg, OpType); /// Parse order by int parseOrderBy(tokenizer &parser, SortingEntries &, std::vector &forcedSortOrder); @@ -114,6 +116,8 @@ class SQLParser { /// Parse merge entries void parseMerge(tokenizer &parser); + Query parseSubQuery(tokenizer &); + static CondType getCondType(std::string_view cond); SqlParsingCtx ctx_; Query &query_; diff --git a/cpp_src/core/query/sql/sqlsuggester.cc b/cpp_src/core/query/sql/sqlsuggester.cc index c8b2cc8da..4cb9e73da 100644 --- a/cpp_src/core/query/sql/sqlsuggester.cc +++ b/cpp_src/core/query/sql/sqlsuggester.cc @@ -1,7 +1,7 @@ #include "sqlsuggester.h" #include "core/namespacedef.h" -#include "core/schema.h" +#include "core/query/query.h" #include "sqltokentype.h" #include @@ -9,27 +9,32 @@ namespace reindexer { -bool checkIfTokenStartsWith(std::string_view src, std::string_view pattern) { +static bool checkIfTokenStartsWith(std::string_view src, std::string_view pattern) { return checkIfStartsWith(src, pattern) && src.length() < pattern.length(); } std::vector SQLSuggester::GetSuggestions(std::string_view q, size_t pos, EnumNamespacesF enumNamespaces, GetSchemaF getSchema) { - ctx_.suggestionsPos = pos; - ctx_.autocompleteMode = true; - enumNamespaces_ = std::move(enumNamespaces); - getSchema_ = std::move(getSchema); + Query query; + SQLSuggester suggester{query}; + suggester.ctx_.suggestionsPos = pos; + suggester.ctx_.autocompleteMode = true; + suggester.enumNamespaces_ = std::move(enumNamespaces); + suggester.getSchema_ = std::move(getSchema); try { - Parse(q); + tokenizer tokens{q}; + (void)(suggester.Parse(tokens)); + // NOLINTBEGIN(bugprone-empty-catch) } catch (const Error &) { } + // NOLINTEND(bugprone-empty-catch) - for (SqlParsingCtx::SuggestionData &item : ctx_.suggestions) { - checkForTokenSuggestions(item); + for (SqlParsingCtx::SuggestionData &item : suggester.ctx_.suggestions) { + suggester.checkForTokenSuggestions(item); } - for (auto &it : ctx_.suggestions) { + for (auto &it : suggester.ctx_.suggestions) { if (!it.variants.empty()) { return it.variants; } diff --git a/cpp_src/core/query/sql/sqlsuggester.h b/cpp_src/core/query/sql/sqlsuggester.h index e0d55ec29..5ece47455 100644 --- a/cpp_src/core/query/sql/sqlsuggester.h +++ b/cpp_src/core/query/sql/sqlsuggester.h @@ -19,10 +19,10 @@ class SQLSuggester : public SQLParser { /// @param pos - pos of cursor in query. /// @param enumNamespaces - functor which enums namespaces to be checked for existing fields. /// @param getSchemaSuggestions - functor which get pointer to namespace's schema - std::vector GetSuggestions(std::string_view q, size_t pos, EnumNamespacesF enumNamespaces, - GetSchemaF getSchemaSuggestions); + [[nodiscard]] static std::vector GetSuggestions(std::string_view q, size_t pos, EnumNamespacesF enumNamespaces, + GetSchemaF getSchemaSuggestions); -protected: +private: /// Finds suggestions for token /// @param ctx - suggestion context. void getSuggestionsForToken(SqlParsingCtx::SuggestionData &ctx); @@ -31,11 +31,11 @@ class SQLSuggester : public SQLParser { void checkForTokenSuggestions(SqlParsingCtx::SuggestionData &data); /// Tries to find token value among accepted tokens. - bool findInPossibleTokens(int type, const std::string &v); + [[nodiscard]] bool findInPossibleTokens(int type, const std::string &v); /// Tries to find token value among indexes. - bool findInPossibleFields(const std::string &tok); + [[nodiscard]] bool findInPossibleFields(const std::string &tok); /// Tries to find among possible namespaces. - bool findInPossibleNamespaces(const std::string &tok); + [[nodiscard]] bool findInPossibleNamespaces(const std::string &tok); /// Gets names of indexes that start with 'token'. void getMatchingFieldsNames(const std::string &token, std::vector &variants); void getMatchingNamespacesNames(const std::string &token, std::vector &variants); diff --git a/cpp_src/core/queryresults/aggregationresult.h b/cpp_src/core/queryresults/aggregationresult.h index b9869f3ae..17f36a22f 100644 --- a/cpp_src/core/queryresults/aggregationresult.h +++ b/cpp_src/core/queryresults/aggregationresult.h @@ -148,4 +148,4 @@ struct AggregationResult { std::optional value_ = std::nullopt; }; -}; // namespace reindexer +} // namespace reindexer diff --git a/cpp_src/core/reindexer.cc b/cpp_src/core/reindexer.cc index 2d0de9a81..982515c82 100644 --- a/cpp_src/core/reindexer.cc +++ b/cpp_src/core/reindexer.cc @@ -1,5 +1,5 @@ #include "core/reindexer.h" -#include "core/reindexerimpl.h" +#include "core/reindexer_impl/reindexerimpl.h" #include "tools/cpucheck.h" namespace reindexer { diff --git a/cpp_src/core/reindexerimpl.cc b/cpp_src/core/reindexer_impl/reindexerimpl.cc similarity index 81% rename from cpp_src/core/reindexerimpl.cc rename to cpp_src/core/reindexer_impl/reindexerimpl.cc index 59e1f48bd..242bb31aa 100644 --- a/cpp_src/core/reindexerimpl.cc +++ b/cpp_src/core/reindexer_impl/reindexerimpl.cc @@ -1,22 +1,24 @@ -#include "core/reindexerimpl.h" +#include "reindexerimpl.h" #include #include #include -#include "cjson/jsonbuilder.h" +#include "core/cjson/jsonbuilder.h" #include "core/cjson/protobufschemabuilder.h" +#include "core/defnsconfigs.h" #include "core/iclientsstats.h" #include "core/index/index.h" #include "core/itemimpl.h" #include "core/nsselecter/crashqueryreporter.h" +#include "core/nsselecter/nsselecter.h" #include "core/nsselecter/querypreprocessor.h" #include "core/query/sql/sqlsuggester.h" +#include "core/queryresults/joinresults.h" #include "core/selectfunc/selectfunc.h" #include "core/type_consts_helpers.h" -#include "defnsconfigs.h" #include "estl/defines.h" -#include "queryresults/joinresults.h" #include "replicator/replicator.h" +#include "rx_selector.h" #include "server/outputparameters.h" #include "tools/alloc_ext/tc_malloc_extension.h" #include "tools/errors.h" @@ -96,7 +98,7 @@ ReindexerImpl::StatsLocker::StatsLocker() { ReindexerImpl::StatsLocker::StatsLockT ReindexerImpl::StatsLocker::LockIfRequired(std::string_view sysNsName, const RdxContext& ctx) { auto found = mtxMap_.find(sysNsName); if (found != mtxMap_.end()) { - return StatsLockT(found->second, &ctx); + return StatsLockT(found->second, ctx); } // Do not create any lock, if namespace does not preset in the map return StatsLockT(); @@ -231,8 +233,9 @@ Error ReindexerImpl::Connect(const std::string& dsn, ConnectOpts opts) { if (!err.ok()) return err; if (enableStorage && opts.IsOpenNamespaces()) { - std::sort(foundNs.begin(), foundNs.end(), - [](const fs::DirEntry& ld, const fs::DirEntry& rd) { return ld.internalFilesCount > rd.internalFilesCount; }); + boost::sort::pdqsort_branchless(foundNs.begin(), foundNs.end(), [](const fs::DirEntry& ld, const fs::DirEntry& rd) noexcept { + return ld.internalFilesCount > rd.internalFilesCount; + }); const size_t maxLoadWorkers = ConcurrentNamespaceLoaders(); std::unique_ptr thrs(new std::thread[maxLoadWorkers]); std::atomic_flag hasNsErrors = ATOMIC_FLAG_INIT; @@ -303,7 +306,7 @@ Error ReindexerImpl::OpenNamespace(std::string_view nsName, const StorageOpts& o const auto rdxCtx = ctx.CreateRdxContext(ctx.NeedTraceActivity() ? (ser << "OPEN NAMESPACE " << nsName).Slice() : ""sv, activities_); { - SLock lock(mtx_, &rdxCtx); + SLock lock(mtx_, rdxCtx); auto it = namespaces_.find(nsName); if (it == namespaces_.end()) { // create new namespace if (!validateUserNsName(nsName)) { @@ -335,7 +338,7 @@ Error ReindexerImpl::addNamespace(const NamespaceDef& nsDef, const RdxContext& r Namespace::Ptr ns; try { { - SLock lock(mtx_, &rdxCtx); + SLock lock(mtx_, rdxCtx); if (namespaces_.find(nsDef.name) != namespaces_.end()) { return Error(errParams, "Namespace '%s' already exists", nsDef.name); } @@ -356,7 +359,7 @@ Error ReindexerImpl::addNamespace(const NamespaceDef& nsDef, const RdxContext& r ns->LoadFromStorage(kStorageLoadingThreads, rdxCtx); } { - ULock lock(mtx_, &rdxCtx); + ULock lock(mtx_, rdxCtx); namespaces_.insert({nsDef.name, ns}); } if (!nsDef.isTemporary) observers_.OnWALUpdate(LSNPair(), nsDef.name, WALRecord(WalNamespaceAdd)); @@ -376,7 +379,7 @@ Error ReindexerImpl::addNamespace(const NamespaceDef& nsDef, const RdxContext& r Error ReindexerImpl::openNamespace(std::string_view name, const StorageOpts& storageOpts, const RdxContext& rdxCtx) { try { { - SLock lock(mtx_, &rdxCtx); + SLock lock(mtx_, rdxCtx); auto nsIt = namespaces_.find(name); if (nsIt != namespaces_.end() && nsIt->second) { if (storageOpts.IsSlaveMode()) nsIt->second->setSlaveMode(rdxCtx); @@ -426,7 +429,7 @@ Error ReindexerImpl::closeNamespace(std::string_view nsName, const RdxContext& c Namespace::Ptr ns; Error err; try { - ULock lock(mtx_, &ctx); + ULock lock(mtx_, ctx); auto nsIt = namespaces_.find(nsName); if (nsIt == namespaces_.end()) { return Error(errNotFound, "Namespace '%s' does not exist", nsName); @@ -498,7 +501,7 @@ Error ReindexerImpl::RenameNamespace(std::string_view srcNsName, const std::stri const auto rdxCtx = ctx.CreateRdxContext( ctx.NeedTraceActivity() ? (ser << "RENAME " << srcNsName << " to " << dstNsName).Slice() : ""sv, activities_); { - SLock lock(mtx_, &rdxCtx); + SLock lock(mtx_, rdxCtx); auto srcIt = namespaces_.find(srcNsName); if (srcIt == namespaces_.end()) { return Error(errParams, "Namespace '%s' doesn't exist", srcNsName); @@ -540,7 +543,7 @@ Error ReindexerImpl::renameNamespace(std::string_view srcNsName, const std::stri { // Perform namespace flushes to minimize chances of the flush under lock - SLock lock(mtx_, &rdxCtx); + SLock lock(mtx_, rdxCtx); auto srcIt = namespaces_.find(srcNsName); srcNs = (srcIt != namespaces_.end()) ? srcIt->second : Namespace::Ptr(); lock.unlock(); @@ -554,7 +557,7 @@ Error ReindexerImpl::renameNamespace(std::string_view srcNsName, const std::stri } } - ULock lock(mtx_, &rdxCtx); + ULock lock(mtx_, rdxCtx); auto srcIt = namespaces_.find(srcNsName); if (srcIt == namespaces_.end()) { return Error(errParams, "Namespace '%s' doesn't exist", srcNsName); @@ -691,6 +694,7 @@ Error ReindexerImpl::Update(std::string_view nsName, Item& item, QueryResults& q Error ReindexerImpl::Update(const Query& q, QueryResults& result, const InternalRdxContext& ctx) { try { + q.VerifyForUpdate(); WrSerializer ser; const auto rdxCtx = ctx.CreateRdxContext(ctx.NeedTraceActivity() ? q.GetSQL(ser).Slice() : ""sv, activities_, result); auto ns = getNamespace(q.NsName(), rdxCtx); @@ -802,6 +806,7 @@ Error ReindexerImpl::Delete(std::string_view nsName, Item& item, QueryResults& q } Error ReindexerImpl::Delete(const Query& q, QueryResults& result, const InternalRdxContext& ctx) { + q.VerifyForUpdate(); const auto makeCtxStr = [&q](WrSerializer& ser) -> WrSerializer& { return q.GetSQL(ser); }; const std::string_view nsName = q.NsName(); APPLY_NS_FUNCTION2(false, Delete, q, result); @@ -810,8 +815,7 @@ Error ReindexerImpl::Delete(const Query& q, QueryResults& result, const Internal Error ReindexerImpl::Select(std::string_view query, QueryResults& result, const InternalRdxContext& ctx) { Error err; try { - Query q; - q.FromSQL(query); + Query q = Query::FromSQL(query); switch (q.type_) { case QuerySelect: err = Select(q, result, ctx); @@ -836,24 +840,12 @@ Error ReindexerImpl::Select(std::string_view query, QueryResults& result, const return err; } -struct ItemRefLess { - bool operator()(const ItemRef& lhs, const ItemRef& rhs) const { - if (lhs.Proc() == rhs.Proc()) { - if (lhs.Nsid() == rhs.Nsid()) { - return lhs.Id() < rhs.Id(); - } - return lhs.Nsid() < rhs.Nsid(); - } - return lhs.Proc() > rhs.Proc(); - } -}; - Error ReindexerImpl::Select(const Query& q, QueryResults& result, const InternalRdxContext& ctx) { try { WrSerializer normalizedSQL, nonNormalizedSQL; if (ctx.NeedTraceActivity()) q.GetSQL(nonNormalizedSQL, false); const auto rdxCtx = ctx.CreateRdxContext(ctx.NeedTraceActivity() ? nonNormalizedSQL.Slice() : "", activities_, result); - NsLocker locks(rdxCtx); + RxSelector::NsLocker locks(rdxCtx); auto mainNsWrp = getNamespace(q.NsName(), rdxCtx); auto mainNs = q.IsWALQuery() ? mainNsWrp->awaitMainNs(rdxCtx) : mainNsWrp->getMainNs(); @@ -891,7 +883,7 @@ Error ReindexerImpl::Select(const Query& q, QueryResults& result, const Internal // Lookup and lock namespaces_ mainNs->updateSelectTime(); locks.Add(mainNs); - q.WalkNested(false, true, [this, &locks, &rdxCtx](const Query& q) { + q.WalkNested(false, true, true, [this, &locks, &rdxCtx](const Query& q) { auto nsWrp = getNamespace(q.NsName(), rdxCtx); auto ns = q.IsWALQuery() ? nsWrp->awaitMainNs(rdxCtx) : nsWrp->getMainNs(); ns->updateSelectTime(); @@ -908,7 +900,7 @@ Error ReindexerImpl::Select(const Query& q, QueryResults& result, const Internal } SelectFunctionsHolder func; - doSelect(q, result, locks, func, rdxCtx, statCalculator); + RxSelector::DoSelect(q, result, locks, func, rdxCtx, statCalculator); func.Process(result); } catch (const Error& err) { if (ctx.Compl()) ctx.Compl()(err); @@ -918,300 +910,6 @@ Error ReindexerImpl::Select(const Query& q, QueryResults& result, const Internal return Error(); } -struct ReindexerImpl::QueryResultsContext { - QueryResultsContext() = default; - QueryResultsContext(PayloadType type, TagsMatcher tagsMatcher, const FieldsSet& fieldsFilter, std::shared_ptr schema) - : type_(std::move(type)), tagsMatcher_(std::move(tagsMatcher)), fieldsFilter_(fieldsFilter), schema_(std::move(schema)) {} - - PayloadType type_; - TagsMatcher tagsMatcher_; - FieldsSet fieldsFilter_; - std::shared_ptr schema_; -}; - -[[nodiscard]] static bool byJoinedField(std::string_view sortExpr, std::string_view joinedNs) { - static const fast_hash_set allowedSymbolsInIndexName{ - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '.', '+'}; - std::string_view::size_type i = 0; - const auto s = sortExpr.size(); - while (i < s && isspace(sortExpr[i])) ++i; - bool inQuotes = false; - if (i < s && sortExpr[i] == '"') { - ++i; - inQuotes = true; - } - while (i < s && isspace(sortExpr[i])) ++i; - std::string_view::size_type j = 0, s2 = joinedNs.size(); - for (; j < s2 && i < s; ++i, ++j) { - if (sortExpr[i] != joinedNs[j]) return false; - } - if (i >= s || sortExpr[i] != '.') return false; - for (++i; i < s; ++i) { - if (allowedSymbolsInIndexName.find(sortExpr[i]) == allowedSymbolsInIndexName.end()) { - if (isspace(sortExpr[i])) break; - if (inQuotes && sortExpr[i] == '"') { - inQuotes = false; - ++i; - break; - } - return false; - } - } - while (i < s && isspace(sortExpr[i])) ++i; - if (inQuotes && i < s && sortExpr[i] == '"') ++i; - while (i < s && isspace(sortExpr[i])) ++i; - return i == s; -} - -bool ReindexerImpl::isPreResultValuesModeOptimizationAvailable(const Query& jItemQ, const NamespaceImpl::Ptr& jns, const Query& mainQ) { - bool result = true; - jItemQ.entries.ExecuteAppropriateForEach( - Skip{}, - [&jns, &result](const QueryEntry& qe) { - if (qe.IsFieldIndexed()) { - assertrx(jns->indexes_.size() > static_cast(qe.IndexNo())); - const IndexType indexType = jns->indexes_[qe.IndexNo()]->Type(); - if (IsComposite(indexType) || IsFullText(indexType)) result = false; - } - }, - [&jns, &result](const BetweenFieldsQueryEntry& qe) { - if (qe.IsLeftFieldIndexed()) { - assertrx(jns->indexes_.size() > static_cast(qe.LeftIdxNo())); - const IndexType indexType = jns->indexes_[qe.LeftIdxNo()]->Type(); - if (IsComposite(indexType) || IsFullText(indexType)) result = false; - } - if (qe.IsRightFieldIndexed()) { - assertrx(jns->indexes_.size() > static_cast(qe.RightIdxNo())); - if (IsComposite(jns->indexes_[qe.RightIdxNo()]->Type())) result = false; - } - }); - if (!result) return false; - for (const auto& se : mainQ.sortingEntries_) { - if (byJoinedField(se.expression, jItemQ.NsName())) return false; // TODO maybe allow #1410 - } - return true; -} - -template -JoinedSelectors ReindexerImpl::prepareJoinedSelectors(const Query& q, QueryResults& result, NsLocker& locks, SelectFunctionsHolder& func, - std::vector& queryResultsContexts, const RdxContext& rdxCtx) { - JoinedSelectors joinedSelectors; - if (q.joinQueries_.empty()) return joinedSelectors; - auto ns = locks.Get(q.NsName()); - assertrx(ns); - - // For each joined queries - uint32_t joinedSelectorsCount = uint32_t(q.joinQueries_.size()); - for (auto& jq : q.joinQueries_) { - if rx_unlikely (isSystemNamespaceNameFast(jq.NsName())) { - throw Error(errParams, "Queries to system namespaces ('%s') are not supported inside JOIN statement", jq.NsName()); - } - if (rx_unlikely(!jq.joinQueries_.empty())) { - throw Error(errParams, "JOINs nested into the other JOINs are not supported"); - } - if (rx_unlikely(!jq.mergeQueries_.empty())) { - throw Error(errParams, "MERGEs nested into the JOINs are not supported"); - } - - // Get common results from joined namespaces_ - auto jns = locks.Get(jq.NsName()); - assertrx(jns); - - // Do join for each item in main result - Query jItemQ(jq.NsName()); - jItemQ.explain_ = q.explain_; - jItemQ.Debug(jq.debugLevel).Limit(jq.Limit()); - jItemQ.Strict(q.strictMode); - for (size_t i = 0; i < jq.sortingEntries_.size(); ++i) { - jItemQ.Sort(jq.sortingEntries_[i].expression, jq.sortingEntries_[i].desc); - } - - jItemQ.entries.Reserve(jq.joinEntries_.size()); - - // Construct join conditions - for (auto& je : jq.joinEntries_) { - QueryPreprocessor::SetQueryField(const_cast(je).LeftFieldData(), *ns); - QueryPreprocessor::SetQueryField(const_cast(je).RightFieldData(), *jns); - jItemQ.entries.Append(je.Operation(), QueryField(je.RightFieldData()), InvertJoinCondition(je.Condition()), - QueryEntry::IgnoreEmptyValues{}); - } - - Query jjq(static_cast(jq)); - JoinPreResult::Ptr preResult = std::make_shared(); - uint32_t joinedFieldIdx = uint32_t(joinedSelectors.size()); - JoinCacheRes joinRes; - jns->getFromJoinCache(jq, joinRes); - jjq.explain_ = q.explain_; - jjq.Strict(q.strictMode); - if (!jjq.entries.Empty() && !joinRes.haveData) { - QueryResults jr; - jjq.Limit(QueryEntry::kDefaultLimit); - SelectCtx ctx(jjq, &q); - ctx.preResult = preResult; - ctx.preResult->executionMode = JoinPreResult::ModeBuild; - ctx.preResult->enableStoredValues = isPreResultValuesModeOptimizationAvailable(jItemQ, jns, q); - ctx.functions = &func; - ctx.requiresCrashTracking = true; - jns->Select(jr, ctx, rdxCtx); - assertrx(ctx.preResult->executionMode == JoinPreResult::ModeExecute); - } - if (joinRes.haveData) { - preResult = joinRes.it.val.preResult; - } else if (joinRes.needPut) { - jns->putToJoinCache(joinRes, preResult); - } - - queryResultsContexts.emplace_back(jns->payloadType_, jns->tagsMatcher_, FieldsSet(jns->tagsMatcher_, jq.selectFilter_), - jns->schema_); - - result.AddNamespace(jns, true); - if (preResult->dataMode == JoinPreResult::ModeValues) { - preResult->values.PreselectAllowed(static_cast(jns->Config().maxPreselectSize) >= preResult->values.size()); - if (!preResult->values.Locked()) preResult->values.Lock(); // If not from cache - locks.Delete(jns); - jns.reset(); - } - joinedSelectors.emplace_back(jq.joinType, ns, std::move(jns), std::move(joinRes), std::move(jItemQ), result, jq, preResult, - joinedFieldIdx, func, joinedSelectorsCount, false, rdxCtx); - ThrowOnCancel(rdxCtx); - } - return joinedSelectors; -} - -template -void ReindexerImpl::doSelect(const Query& q, QueryResults& result, NsLocker& locks, SelectFunctionsHolder& func, const RdxContext& ctx, - QueryStatCalculator& queryStatCalculator) { - auto ns = locks.Get(q.NsName()); - if rx_unlikely (!ns) { - throw Error(errParams, "Namespace '%s' does not exist", q.NsName()); - } - std::vector joinQueryResultsContexts; - bool thereAreJoins = !q.joinQueries_.empty(); - if (!thereAreJoins) { - for (const Query& mq : q.mergeQueries_) { - if (!mq.joinQueries_.empty()) { - thereAreJoins = true; - break; - } - } - } - - JoinedSelectors mainJoinedSelectors; - ExplainCalc::Duration preselectTimeTotal{0}; - if (thereAreJoins) { - const auto preselectStartTime = ExplainCalc::Clock::now(); - mainJoinedSelectors = prepareJoinedSelectors(q, result, locks, func, joinQueryResultsContexts, ctx); - result.joined_.resize(1 + q.mergeQueries_.size()); - preselectTimeTotal = ExplainCalc::Clock::now() - preselectStartTime; - } - IsFTQuery isFtQuery{IsFTQuery::NotSet}; - { - SelectCtx selCtx(q, nullptr); - selCtx.joinedSelectors = mainJoinedSelectors.size() ? &mainJoinedSelectors : nullptr; - selCtx.preResultTimeTotal = preselectTimeTotal; - selCtx.contextCollectingMode = true; - selCtx.functions = &func; - selCtx.nsid = 0; - if (!q.mergeQueries_.empty()) { - selCtx.isMergeQuery = IsMergeQuery::Yes; - if rx_unlikely (!q.sortingEntries_.empty()) { - throw Error{errNotValid, "Sorting in merge query is not implemented yet"}; // TODO #1449 - } - for (const auto& a : q.aggregations_) { - switch (a.Type()) { - case AggCount: - case AggCountCached: - case AggSum: - case AggMin: - case AggMax: - continue; - case AggAvg: - case AggFacet: - case AggDistinct: - case AggUnknown: - throw Error{errNotValid, "Aggregation '%s' in merge query is not implemented yet", - AggTypeToStr(a.Type())}; // TODO #1506 - } - } - } - selCtx.requiresCrashTracking = true; - ns->Select(result, selCtx, ctx); - result.AddNamespace(ns, true); - isFtQuery = selCtx.isFtQuery; - if (selCtx.explain.IsEnabled()) { - queryStatCalculator.AddExplain(selCtx.explain); - } - } - // should be destroyed after results.lockResults() - std::vector mergeJoinedSelectors; - if (!q.mergeQueries_.empty()) { - mergeJoinedSelectors.reserve(q.mergeQueries_.size()); - uint8_t counter = 0; - - auto hasUnsupportedAggregations = [](const std::vector& aggVector, AggType& t) -> bool { - for (const auto& a : aggVector) { - if (a.Type() != AggCount || a.Type() != AggCountCached) { - t = a.Type(); - return true; - } - } - t = AggUnknown; - return false; - }; - AggType errType; - if (rx_unlikely((q.HasLimit() || q.HasOffset()) && hasUnsupportedAggregations(q.aggregations_, errType))) { - throw Error(errParams, "Limit and offset are not supported for aggregations '%s'", AggTypeToStr(errType)); - } - for (auto& mq : q.mergeQueries_) { - if rx_unlikely (isSystemNamespaceNameFast(mq.NsName())) { - throw Error(errParams, "Queries to system namespaces ('%s') are not supported inside MERGE statement", mq.NsName()); - } - if rx_unlikely (!mq.sortingEntries_.empty()) { - throw Error(errParams, "Sorting in inner merge query is not allowed"); - } - if rx_unlikely (!mq.aggregations_.empty() || mq.CalcTotal() != ModeNoTotal) { - throw Error(errParams, "Aggregations in inner merge query is not allowed"); - } - if rx_unlikely (mq.HasLimit() || mq.HasOffset()) { - throw Error(errParams, "Limit and offset in inner merge query is not allowed"); - } - if rx_unlikely (!mq.mergeQueries_.empty()) { - throw Error(errParams, "MERGEs nested into the MERGEs are not supported"); - } - - auto mns = locks.Get(mq.NsName()); - assertrx(mns); - SelectCtx mctx(mq, &q); - mctx.nsid = ++counter; - mctx.isMergeQuery = IsMergeQuery::Yes; - mctx.isFtQuery = isFtQuery; - mctx.functions = &func; - mctx.contextCollectingMode = true; - mergeJoinedSelectors.emplace_back(prepareJoinedSelectors(mq, result, locks, func, joinQueryResultsContexts, ctx)); - mctx.joinedSelectors = mergeJoinedSelectors.back().size() ? &mergeJoinedSelectors.back() : nullptr; - mctx.requiresCrashTracking = true; - mns->Select(result, mctx, ctx); - result.AddNamespace(mns, true); - } - ItemRefVector& itemRefVec = result.Items(); - if (q.Offset() >= itemRefVec.size()) { - result.Erase(itemRefVec.begin(), itemRefVec.end()); - return; - } - std::sort(itemRefVec.begin(), itemRefVec.end(), ItemRefLess()); - if (q.HasOffset()) { - result.Erase(itemRefVec.begin(), itemRefVec.begin() + q.Offset()); - } - if (itemRefVec.size() > q.Limit()) { - result.Erase(itemRefVec.begin() + q.Limit(), itemRefVec.end()); - } - } - // Adding context to QueryResults - for (const auto& jctx : joinQueryResultsContexts) result.addNSContext(jctx.type_, jctx.tagsMatcher_, jctx.fieldsFilter_, jctx.schema_); -} - Error ReindexerImpl::Commit(std::string_view /*_namespace*/) { try { // getNamespace(_namespace)->FlushStorage(); @@ -1224,7 +922,7 @@ Error ReindexerImpl::Commit(std::string_view /*_namespace*/) { } Namespace::Ptr ReindexerImpl::getNamespace(std::string_view nsName, const RdxContext& ctx) { - SLock lock(mtx_, &ctx); + SLock lock(mtx_, ctx); auto nsIt = namespaces_.find(nsName); if (nsIt == namespaces_.end()) { throw Error(errParams, "Namespace '%s' does not exist", nsName); @@ -1235,7 +933,7 @@ Namespace::Ptr ReindexerImpl::getNamespace(std::string_view nsName, const RdxCon } Namespace::Ptr ReindexerImpl::getNamespaceNoThrow(std::string_view nsName, const RdxContext& ctx) { - SLock lock(mtx_, &ctx); + SLock lock(mtx_, ctx); auto nsIt = namespaces_.find(nsName); return (nsIt == namespaces_.end()) ? nullptr : nsIt->second; } @@ -1279,7 +977,7 @@ Error ReindexerImpl::DropIndex(std::string_view nsName, const IndexDef& indexDef } std::vector> ReindexerImpl::getNamespaces(const RdxContext& ctx) { - SLock lock(mtx_, &ctx); + SLock lock(mtx_, ctx); std::vector> ret; ret.reserve(namespaces_.size()); for (auto& ns : namespaces_) { @@ -1290,7 +988,7 @@ std::vector> ReindexerImpl::getNamespaces std::vector ReindexerImpl::getNamespacesNames(const RdxContext& ctx) { std::vector ret; - SLock lock(mtx_, &ctx); + SLock lock(mtx_, ctx); ret.reserve(namespaces_.size()); for (auto& ns : namespaces_) { ret.emplace_back(); @@ -1322,20 +1020,22 @@ Error ReindexerImpl::EnumNamespaces(std::vector& defs, EnumNamespa for (auto& d : dirs) { if (d.isDir && d.name != "." && d.name != ".." && opts.MatchFilter(d.name)) { { - SLock lock(mtx_, &rdxCtx); + SLock lock(mtx_, rdxCtx); if (namespaces_.find(d.name) != namespaces_.end()) continue; } std::unique_ptr tmpNs{new NamespaceImpl(d.name, observers_)}; try { tmpNs->EnableStorage(storagePath_, StorageOpts(), storageType_, rdxCtx); defs.push_back(tmpNs->GetDefinition(rdxCtx)); - } catch (reindexer::Error) { + // NOLINTBEGIN(bugprone-empty-catch) + } catch (const Error&) { } + // NOLINTEND(bugprone-empty-catch) } } } - } catch (reindexer::Error err) { - return err.code(); + } catch (const Error& err) { + return err; } return errOK; } @@ -1610,10 +1310,7 @@ void ReindexerImpl::updateReplicationConfFile() { auto err = replConfigFileChecker_.RewriteFile(std::string(ser.Slice()), [&oldReplConf](const std::string& content) { ReplicationConfigData replConf; Error err = replConf.FromYML(content); - if (err.ok()) { - return replConf == oldReplConf; - } - return false; + return err.ok() && (replConf == oldReplConf); }); if (!err.ok()) { throw err; @@ -1628,13 +1325,13 @@ ReindexerImpl::FilterNsNamesT ReindexerImpl::detectFilterNsNames(const Query& q) }; h_vector notBrackets; - const auto& entries = q.entries; + const auto& entries = q.Entries(); for (uint32_t i = 0, sz = entries.Size(); i < sz; ++i) { const auto op = entries.GetOperation(i); if (op == OpOr) { return std::nullopt; } - if (entries.HoldsOrReferTo(i)) { + if (entries.Is(i)) { auto& qe = entries.Get(i); if (qe.FieldName() == kNsNameField) { if (op == OpNot) { @@ -1659,7 +1356,7 @@ ReindexerImpl::FilterNsNamesT ReindexerImpl::detectFilterNsNames(const Query& q) res->emplace_back(v.As()); } } - } else if (entries.HoldsOrReferTo(i)) { + } else if (entries.Is(i)) { auto& qe = entries.Get(i); if (qe.LeftFieldName() == kNsNameField || qe.RightFieldName() == kNsNameField) { return std::nullopt; @@ -1668,7 +1365,7 @@ ReindexerImpl::FilterNsNamesT ReindexerImpl::detectFilterNsNames(const Query& q) notBrackets.emplace_back(BracketRange{.begin = i, .end = uint32_t(entries.Size(i))}); } } - for (auto& jq : q.joinQueries_) { + for (auto& jq : q.GetJoinQueries()) { if (jq.joinType == OrInnerJoin) { return std::nullopt; } @@ -1830,11 +1527,9 @@ Error ReindexerImpl::UnsubscribeUpdates(IUpdatesObserver* observer) { return obs Error ReindexerImpl::GetSqlSuggestions(const std::string_view sqlQuery, int pos, std::vector& suggestions, const InternalRdxContext& ctx) { - Query query; - SQLSuggester suggester(query); std::vector nses; - suggestions = suggester.GetSuggestions( + suggestions = SQLSuggester::GetSuggestions( sqlQuery, pos, [&, this](EnumNamespacesOpts opts) { EnumNamespaces(nses, opts, ctx); diff --git a/cpp_src/core/reindexerimpl.h b/cpp_src/core/reindexer_impl/reindexerimpl.h similarity index 79% rename from cpp_src/core/reindexerimpl.h rename to cpp_src/core/reindexer_impl/reindexerimpl.h index f8ef5736d..57032c01f 100644 --- a/cpp_src/core/reindexerimpl.h +++ b/cpp_src/core/reindexer_impl/reindexerimpl.h @@ -5,21 +5,19 @@ #include #include +#include "core/dbconfig.h" #include "core/namespace/namespace.h" -#include "core/nsselecter/nsselecter.h" +#include "core/querystat.h" #include "core/rdxcontext.h" -#include "dbconfig.h" +#include "core/reindexerconfig.h" +#include "core/transaction.h" #include "estl/fast_hash_map.h" #include "estl/h_vector.h" -#include "estl/smart_lock.h" #include "net/ev/ev.h" -#include "querystat.h" -#include "reindexerconfig.h" #include "replicator/updatesobserver.h" #include "tools/errors.h" #include "tools/filecontentwatcher.h" #include "tools/tcmallocheapwathcher.h" -#include "transaction.h" namespace reindexer { @@ -30,12 +28,6 @@ class ProtobufSchema; class ReindexerImpl { using Mutex = MarkedMutex; using StatsSelectMutex = MarkedMutex; - struct NsLockerItem { - NsLockerItem(NamespaceImpl::Ptr ins = {}) : ns(std::move(ins)), count(1) {} - NamespaceImpl::Ptr ns; - NamespaceImpl::Locker::RLockT nsLck; - unsigned count = 1; - }; template Error applyNsFunction(std::string_view nsName, const InternalRdxContext &ctx, const MakeCtxStrFn &makeCtxStr, Arg arg, Args... args); @@ -100,69 +92,11 @@ class ReindexerImpl { Error DumpIndex(std::ostream &os, std::string_view nsName, std::string_view index, const InternalRdxContext &ctx = InternalRdxContext()); -protected: +private: typedef contexted_shared_lock SLock; typedef contexted_unique_lock ULock; using FilterNsNamesT = std::optional>; - template - class NsLocker : private h_vector { - public: - NsLocker(const Context &context) : context_(context) {} - ~NsLocker() { - // Unlock first - for (auto it = rbegin(); it != rend(); ++it) { - // Some of the namespaces may be in unlocked statet in case of the exception during Lock() call - if (it->nsLck.owns_lock()) { - it->nsLck.unlock(); - } else { - assertrx(!locked_); - } - } - // Clean (ns may releases, if locker holds last ref) - } - - void Add(NamespaceImpl::Ptr ns) { - assertrx(!locked_); - for (auto it = begin(); it != end(); ++it) { - if (it->ns.get() == ns.get()) { - ++(it->count); - return; - } - } - - emplace_back(std::move(ns)); - return; - } - void Delete(const NamespaceImpl::Ptr &ns) { - for (auto it = begin(); it != end(); ++it) { - if (it->ns.get() == ns.get()) { - if (!--(it->count)) erase(it); - return; - } - } - assertrx(0); - } - void Lock() { - std::sort(begin(), end(), [](const NsLockerItem &lhs, const NsLockerItem &rhs) { return lhs.ns.get() < rhs.ns.get(); }); - for (auto it = begin(); it != end(); ++it) { - it->nsLck = it->ns->rLock(context_); - } - locked_ = true; - } - - NamespaceImpl::Ptr Get(const std::string &name) { - for (auto it = begin(); it != end(); it++) { - if (iequals(it->ns->name_, name)) return it->ns; - } - return nullptr; - } - - protected: - bool locked_ = false; - const Context &context_; - }; - class BackgroundThread { public: ~BackgroundThread() { Stop(); } @@ -200,15 +134,6 @@ class ReindexerImpl { std::unordered_map mtxMap_; }; - template - void doSelect(const Query &q, QueryResults &result, NsLocker &locks, SelectFunctionsHolder &func, const RdxContext &ctx, - QueryStatCalculator &queryStatCalculator); - struct QueryResultsContext; - template - JoinedSelectors prepareJoinedSelectors(const Query &q, QueryResults &result, NsLocker &locks, SelectFunctionsHolder &func, - std::vector &, const RdxContext &ctx); - static bool isPreResultValuesModeOptimizationAvailable(const Query &jItemQ, const NamespaceImpl::Ptr &jns, const Query &mainQ); - FilterNsNamesT detectFilterNsNames(const Query &q); [[nodiscard]] StatsLocker::StatsLockT syncSystemNamespaces(std::string_view sysNsName, const FilterNsNamesT &, const RdxContext &); void createSystemNamespaces(); diff --git a/cpp_src/core/reindexer_impl/rx_selector.cc b/cpp_src/core/reindexer_impl/rx_selector.cc new file mode 100644 index 000000000..ffc87deb5 --- /dev/null +++ b/cpp_src/core/reindexer_impl/rx_selector.cc @@ -0,0 +1,499 @@ +#include "rx_selector.h" +#include "core/nsselecter/nsselecter.h" +#include "core/nsselecter/querypreprocessor.h" +#include "core/queryresults/joinresults.h" +#include "tools/logger.h" + +namespace reindexer { + +struct ItemRefLess { + bool operator()(const ItemRef& lhs, const ItemRef& rhs) const noexcept { + if (lhs.Proc() == rhs.Proc()) { + if (lhs.Nsid() == rhs.Nsid()) { + return lhs.Id() < rhs.Id(); + } + return lhs.Nsid() < rhs.Nsid(); + } + return lhs.Proc() > rhs.Proc(); + } +}; + +struct RxSelector::QueryResultsContext { + QueryResultsContext() = default; + QueryResultsContext(PayloadType type, TagsMatcher tagsMatcher, const FieldsSet& fieldsFilter, std::shared_ptr schema) + : type_(std::move(type)), tagsMatcher_(std::move(tagsMatcher)), fieldsFilter_(fieldsFilter), schema_(std::move(schema)) {} + + PayloadType type_; + TagsMatcher tagsMatcher_; + FieldsSet fieldsFilter_; + std::shared_ptr schema_; +}; + +template +void RxSelector::DoSelect(const Query& q, QueryResults& result, NsLocker& locks, SelectFunctionsHolder& func, const RdxContext& ctx, + QueryStatCalculator& queryStatCalculator) { + auto ns = locks.Get(q.NsName()); + if rx_unlikely (!ns) { + throw Error(errParams, "Namespace '%s' does not exist", q.NsName()); + } + std::vector queryResultsHolder; + std::optional queryCopy; + if (!q.GetSubQueries().empty()) { + if (q.GetDebugLevel() >= LogInfo || ns->config_.logLevel >= LogInfo) { + logPrintf(LogInfo, "Query before subqueries substitution: %s", q.GetSQL()); + } + queryCopy.emplace(q); + preselectSubQueries(*queryCopy, queryResultsHolder, locks, func, ctx); + } + const Query& query = queryCopy ? *queryCopy : q; + std::vector joinQueryResultsContexts; + bool thereAreJoins = !query.GetJoinQueries().empty(); + if (!thereAreJoins) { + for (const Query& mq : query.GetMergeQueries()) { + if (!mq.GetJoinQueries().empty()) { + thereAreJoins = true; + break; + } + } + } + + JoinedSelectors mainJoinedSelectors; + ExplainCalc::Duration preselectTimeTotal{0}; + if (thereAreJoins) { + const auto preselectStartTime = ExplainCalc::Clock::now(); + mainJoinedSelectors = prepareJoinedSelectors(query, result, locks, func, joinQueryResultsContexts, ctx); + result.joined_.resize(1 + query.GetMergeQueries().size()); + preselectTimeTotal = ExplainCalc::Clock::now() - preselectStartTime; + } + IsFTQuery isFtQuery{IsFTQuery::NotSet}; + { + SelectCtx selCtx(query, nullptr); + selCtx.joinedSelectors = mainJoinedSelectors.size() ? &mainJoinedSelectors : nullptr; + selCtx.preResultTimeTotal = preselectTimeTotal; + selCtx.contextCollectingMode = true; + selCtx.functions = &func; + selCtx.nsid = 0; + if (!query.GetMergeQueries().empty()) { + selCtx.isMergeQuery = IsMergeQuery::Yes; + if rx_unlikely (!query.sortingEntries_.empty()) { + throw Error{errNotValid, "Sorting in merge query is not implemented yet"}; // TODO #1449 + } + for (const auto& a : query.aggregations_) { + switch (a.Type()) { + case AggCount: + case AggCountCached: + case AggSum: + case AggMin: + case AggMax: + continue; + case AggAvg: + case AggFacet: + case AggDistinct: + case AggUnknown: + throw Error{errNotValid, "Aggregation '%s' in merge query is not implemented yet", + AggTypeToStr(a.Type())}; // TODO #1506 + } + } + } + selCtx.requiresCrashTracking = true; + ns->Select(result, selCtx, ctx); + result.AddNamespace(ns, true); + isFtQuery = selCtx.isFtQuery; + if (selCtx.explain.IsEnabled()) { + queryStatCalculator.AddExplain(selCtx.explain); + } + } + // should be destroyed after results.lockResults() + std::vector mergeJoinedSelectors; + if (!query.GetMergeQueries().empty()) { + mergeJoinedSelectors.reserve(query.GetMergeQueries().size()); + uint8_t counter = 0; + + auto hasUnsupportedAggregations = [](const std::vector& aggVector, AggType& t) -> bool { + for (const auto& a : aggVector) { + if (a.Type() != AggCount || a.Type() != AggCountCached) { + t = a.Type(); + return true; + } + } + t = AggUnknown; + return false; + }; + AggType errType; + if (rx_unlikely((query.HasLimit() || query.HasOffset()) && hasUnsupportedAggregations(query.aggregations_, errType))) { + throw Error(errParams, "Limit and offset are not supported for aggregations '%s'", AggTypeToStr(errType)); + } + for (const JoinedQuery& mq : query.GetMergeQueries()) { + if rx_unlikely (isSystemNamespaceNameFast(mq.NsName())) { + throw Error(errParams, "Queries to system namespaces ('%s') are not supported inside MERGE statement", mq.NsName()); + } + if rx_unlikely (!mq.sortingEntries_.empty()) { + throw Error(errParams, "Sorting in inner merge query is not allowed"); + } + if rx_unlikely (!mq.aggregations_.empty() || mq.HasCalcTotal()) { + throw Error(errParams, "Aggregations in inner merge query are not allowed"); + } + if rx_unlikely (mq.HasLimit() || mq.HasOffset()) { + throw Error(errParams, "Limit and offset in inner merge query is not allowed"); + } + if rx_unlikely (!mq.GetMergeQueries().empty()) { + throw Error(errParams, "MERGEs nested into the MERGEs are not supported"); + } + std::optional mQueryCopy; + if (!mq.GetSubQueries().empty()) { + mQueryCopy.emplace(mq); + preselectSubQueries(*mQueryCopy, queryResultsHolder, locks, func, ctx); + } + const JoinedQuery& mQuery = mQueryCopy ? *mQueryCopy : mq; + + auto mns = locks.Get(mQuery.NsName()); + assertrx_throw(mns); + SelectCtx mctx(mQuery, &query); + mctx.nsid = ++counter; + mctx.isMergeQuery = IsMergeQuery::Yes; + mctx.isFtQuery = isFtQuery; + mctx.functions = &func; + mctx.contextCollectingMode = true; + mergeJoinedSelectors.emplace_back(prepareJoinedSelectors(mQuery, result, locks, func, joinQueryResultsContexts, ctx)); + mctx.joinedSelectors = mergeJoinedSelectors.back().size() ? &mergeJoinedSelectors.back() : nullptr; + mctx.requiresCrashTracking = true; + mns->Select(result, mctx, ctx); + result.AddNamespace(mns, true); + } + ItemRefVector& itemRefVec = result.Items(); + if (query.Offset() >= itemRefVec.size()) { + result.Erase(itemRefVec.begin(), itemRefVec.end()); + return; + } + boost::sort::pdqsort(itemRefVec.begin(), itemRefVec.end(), ItemRefLess()); + if (query.HasOffset()) { + result.Erase(itemRefVec.begin(), itemRefVec.begin() + query.Offset()); + } + if (itemRefVec.size() > query.Limit()) { + result.Erase(itemRefVec.begin() + query.Limit(), itemRefVec.end()); + } + } + // Adding context to QueryResults + for (const auto& jctx : joinQueryResultsContexts) result.addNSContext(jctx.type_, jctx.tagsMatcher_, jctx.fieldsFilter_, jctx.schema_); +} + +[[nodiscard]] static bool byJoinedField(std::string_view sortExpr, std::string_view joinedNs) { + static const fast_hash_set allowedSymbolsInIndexName{ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '.', '+'}; + std::string_view::size_type i = 0; + const auto s = sortExpr.size(); + while (i < s && isspace(sortExpr[i])) ++i; + bool inQuotes = false; + if (i < s && sortExpr[i] == '"') { + ++i; + inQuotes = true; + } + while (i < s && isspace(sortExpr[i])) ++i; + std::string_view::size_type j = 0, s2 = joinedNs.size(); + for (; j < s2 && i < s; ++i, ++j) { + if (sortExpr[i] != joinedNs[j]) return false; + } + if (i >= s || sortExpr[i] != '.') return false; + for (++i; i < s; ++i) { + if (allowedSymbolsInIndexName.find(sortExpr[i]) == allowedSymbolsInIndexName.end()) { + if (isspace(sortExpr[i])) break; + if (inQuotes && sortExpr[i] == '"') { + inQuotes = false; + ++i; + break; + } + return false; + } + } + while (i < s && isspace(sortExpr[i])) ++i; + if (inQuotes && i < s && sortExpr[i] == '"') ++i; + while (i < s && isspace(sortExpr[i])) ++i; + return i == s; +} + +bool RxSelector::isPreResultValuesModeOptimizationAvailable(const Query& jItemQ, const NamespaceImpl::Ptr& jns, const Query& mainQ) { + bool result = true; + jItemQ.Entries().ExecuteAppropriateForEach([](const SubQueryEntry&) { assertrx_throw(0); }, + [](const SubQueryFieldEntry&) { assertrx_throw(0); }, + Skip{}, + [&jns, &result](const QueryEntry& qe) { + if (qe.IsFieldIndexed()) { + assertrx_throw(jns->indexes_.size() > static_cast(qe.IndexNo())); + const IndexType indexType = jns->indexes_[qe.IndexNo()]->Type(); + if (IsComposite(indexType) || IsFullText(indexType)) result = false; + } + }, + [&jns, &result](const BetweenFieldsQueryEntry& qe) { + if (qe.IsLeftFieldIndexed()) { + assertrx_throw(jns->indexes_.size() > static_cast(qe.LeftIdxNo())); + const IndexType indexType = jns->indexes_[qe.LeftIdxNo()]->Type(); + if (IsComposite(indexType) || IsFullText(indexType)) result = false; + } + if (qe.IsRightFieldIndexed()) { + assertrx_throw(jns->indexes_.size() > static_cast(qe.RightIdxNo())); + if (IsComposite(jns->indexes_[qe.RightIdxNo()]->Type())) result = false; + } + }); + if (!result) return false; + for (const auto& se : mainQ.sortingEntries_) { + if (byJoinedField(se.expression, jItemQ.NsName())) return false; // TODO maybe allow #1410 + } + return true; +} + +template +bool RxSelector::selectSubQuery(const Query& subQuery, const Query& mainQuery, NsLocker& locks, SelectFunctionsHolder& func, + const RdxContext& rdxCtx) { + auto ns = locks.Get(subQuery.NsName()); + assertrx_throw(ns); + + SelectCtx sctx{subQuery, &mainQuery}; + sctx.nsid = 0; + sctx.requiresCrashTracking = true; + sctx.reqMatchedOnceFlag = true; + sctx.contextCollectingMode = true; + sctx.functions = &func; + + QueryResults result; + ns->Select(result, sctx, rdxCtx); + locks.Delete(ns); + return sctx.matchedAtLeastOnce; +} + +template +VariantArray RxSelector::selectSubQuery(const Query& subQuery, const Query& mainQuery, NsLocker& locks, QueryResults& qr, + SelectFunctionsHolder& func, const RdxContext& rdxCtx) { + NamespaceImpl::Ptr ns = locks.Get(subQuery.NsName()); + assertrx_throw(ns); + + SelectCtx sctx{subQuery, &mainQuery}; + sctx.nsid = 0; + sctx.requiresCrashTracking = true; + sctx.contextCollectingMode = true; + sctx.functions = &func; + + ns->Select(qr, sctx, rdxCtx); + VariantArray result, buf; + if (qr.GetAggregationResults().empty()) { + assertrx_throw(!subQuery.SelectFilters().empty()); + const std::string_view field = subQuery.SelectFilters()[0]; + result.reserve(qr.Count()); + if (int idxNo = -1; ns->getIndexByNameOrJsonPath(field, idxNo) && !ns->indexes_[idxNo]->Opts().IsSparse()) { + if (idxNo < ns->indexes_.firstCompositePos()) { + for (const auto& it : qr) { + if (!it.Status().ok()) { + throw it.Status(); + } + ConstPayload{ns->payloadType_, ns->items_[it.GetItemRef().Id()]}.Get(idxNo, buf); + for (Variant& v : buf) { + result.emplace_back(std::move(v)); + } + } + } else { + const auto fields = ns->indexes_[idxNo]->Fields(); + std::vector fieldsTypes; +#ifndef NDEBUG + const bool ftIdx = IsFullText(ns->indexes_[idxNo]->Type()); +#endif + for (const auto f : ns->indexes_[idxNo]->Fields()) { + if (f == IndexValueType::SetByJsonPath) { + // not indexed fields allowed only in ft composite indexes + assertrx_throw(ftIdx); + fieldsTypes.push_back(KeyValueType::String{}); + } else { + assertrx_throw(f <= ns->indexes_.firstCompositePos()); + fieldsTypes.push_back(ns->indexes_[f]->SelectKeyType()); + } + } + for (const auto& it : qr) { + if (!it.Status().ok()) { + throw it.Status(); + } + result.emplace_back(ConstPayload{ns->payloadType_, ns->items_[it.GetItemRef().Id()]}.GetComposite(fields, fieldsTypes)); + } + } + } else { + if (idxNo < 0) { + switch (mainQuery.GetStrictMode()) { + case StrictModeIndexes: + throw Error(errParams, + "Current query strict mode allows aggregate index fields only. There are no indexes with name '%s' in " + "namespace '%s'", + field, subQuery.NsName()); + case StrictModeNames: + if (ns->tagsMatcher_.path2tag(field).empty()) { + throw Error(errParams, + "Current query strict mode allows aggregate existing fields only. There are no fields with name " + "'%s' in namespace '%s'", + field, subQuery.NsName()); + } + break; + case StrictModeNone: + case StrictModeNotSet: + break; + } + } + for (const auto& it : qr) { + if (!it.Status().ok()) { + throw it.Status(); + } + ConstPayload{ns->payloadType_, ns->items_[it.GetItemRef().Id()]}.GetByJsonPath(field, ns->tagsMatcher_, buf, + KeyValueType::Undefined{}); + for (Variant& v : buf) { + result.emplace_back(std::move(v)); + } + } + } + } else { + const auto v = qr.GetAggregationResults()[0].GetValue(); + if (v.has_value()) { + result.emplace_back(*v); + } + } + locks.Delete(ns); + return result; +} + +template +JoinedSelectors RxSelector::prepareJoinedSelectors(const Query& q, QueryResults& result, NsLocker& locks, SelectFunctionsHolder& func, + std::vector& queryResultsContexts, const RdxContext& rdxCtx) { + JoinedSelectors joinedSelectors; + if (q.GetJoinQueries().empty()) return joinedSelectors; + auto ns = locks.Get(q.NsName()); + assertrx_throw(ns); + + // For each joined queries + uint32_t joinedSelectorsCount = uint32_t(q.GetJoinQueries().size()); + for (auto& jq : q.GetJoinQueries()) { + if rx_unlikely (isSystemNamespaceNameFast(jq.NsName())) { + throw Error(errParams, "Queries to system namespaces ('%s') are not supported inside JOIN statement", jq.NsName()); + } + if rx_unlikely (!jq.GetJoinQueries().empty()) { + throw Error(errParams, "JOINs nested into the other JOINs are not supported"); + } + if rx_unlikely (!jq.GetMergeQueries().empty()) { + throw Error(errParams, "MERGEs nested into the JOINs are not supported"); + } + if rx_unlikely (!jq.GetSubQueries().empty()) { + throw Error(errParams, "Subquery in the JOINs are not supported"); + } + if rx_unlikely (!jq.aggregations_.empty()) { + throw Error(errParams, "Aggregations are not allowed in joined subqueries"); + } + if rx_unlikely (jq.HasCalcTotal()) { + throw Error(errParams, "Count()/count_cached() are not allowed in joined subqueries"); + } + + // Get common results from joined namespaces_ + auto jns = locks.Get(jq.NsName()); + assertrx_throw(jns); + + // Do join for each item in main result + Query jItemQ(jq.NsName()); + jItemQ.Explain(q.GetExplain()); + jItemQ.Debug(jq.GetDebugLevel()).Limit(jq.Limit()); + jItemQ.Strict(q.GetStrictMode()); + for (size_t i = 0; i < jq.sortingEntries_.size(); ++i) { + jItemQ.Sort(jq.sortingEntries_[i].expression, jq.sortingEntries_[i].desc); + } + + jItemQ.ReserveQueryEntries(jq.joinEntries_.size()); + + // Construct join conditions + for (auto& je : jq.joinEntries_) { + QueryPreprocessor::SetQueryField(const_cast(je).LeftFieldData(), *ns); + QueryPreprocessor::SetQueryField(const_cast(je).RightFieldData(), *jns); + jItemQ.AppendQueryEntry(je.Operation(), QueryField(je.RightFieldData()), InvertJoinCondition(je.Condition()), + QueryEntry::IgnoreEmptyValues{}); + } + + Query jjq(static_cast(jq)); + JoinPreResult::Ptr preResult = std::make_shared(); + uint32_t joinedFieldIdx = uint32_t(joinedSelectors.size()); + JoinCacheRes joinRes; + jns->getFromJoinCache(jq, joinRes); + if (!jjq.Entries().Empty() && !joinRes.haveData) { + QueryResults jr; + jjq.Limit(QueryEntry::kDefaultLimit); + SelectCtx ctx(jjq, &q); + ctx.preResult = preResult; + ctx.preResult->executionMode = JoinPreResult::ModeBuild; + ctx.preResult->enableStoredValues = isPreResultValuesModeOptimizationAvailable(jItemQ, jns, q); + ctx.functions = &func; + ctx.requiresCrashTracking = true; + jns->Select(jr, ctx, rdxCtx); + assertrx_throw(ctx.preResult->executionMode == JoinPreResult::ModeExecute); + } + if (joinRes.haveData) { + preResult = joinRes.it.val.preResult; + } else if (joinRes.needPut) { + jns->putToJoinCache(joinRes, preResult); + } + + queryResultsContexts.emplace_back(jns->payloadType_, jns->tagsMatcher_, FieldsSet(jns->tagsMatcher_, jq.SelectFilters()), + jns->schema_); + + result.AddNamespace(jns, true); + if (preResult->dataMode == JoinPreResult::ModeValues) { + preResult->values.PreselectAllowed(static_cast(jns->Config().maxPreselectSize) >= preResult->values.size()); + if (!preResult->values.Locked()) preResult->values.Lock(); // If not from cache + locks.Delete(jns); + jns.reset(); + } + joinedSelectors.emplace_back(jq.joinType, ns, std::move(jns), std::move(joinRes), std::move(jItemQ), result, jq, preResult, + joinedFieldIdx, func, joinedSelectorsCount, false, rdxCtx); + ThrowOnCancel(rdxCtx); + } + return joinedSelectors; +} + +template +void RxSelector::preselectSubQueries(Query& mainQuery, std::vector& queryResultsHolder, NsLocker& locks, + SelectFunctionsHolder& func, const RdxContext& ctx) { + for (size_t i = 0, s = mainQuery.Entries().Size(); i < s; ++i) { + mainQuery.Entries().InvokeAppropriate( + i, Skip{}, + [&](const SubQueryEntry& sqe) { + try { + const CondType cond = sqe.Condition(); + if (cond == CondAny || cond == CondEmpty) { + if (selectSubQuery(mainQuery.GetSubQuery(sqe.QueryIndex()), mainQuery, locks, func, ctx) == (cond == CondAny)) { + mainQuery.SetEntry(i); + } else { + mainQuery.SetEntry(i); + } + } else { + QueryResults qr; + const auto values = selectSubQuery(mainQuery.GetSubQuery(sqe.QueryIndex()), mainQuery, locks, qr, func, ctx); + if (QueryEntries::CheckIfSatisfyCondition(values, sqe.Condition(), sqe.Values())) { + mainQuery.SetEntry(i); + } else { + mainQuery.SetEntry(i); + } + } + } catch (const Error& err) { + throw Error(err.code(), "Error during preprocessing of subquery '" + mainQuery.GetSubQuery(sqe.QueryIndex()).GetSQL() + + "': " + err.what()); + } + }, + [&](const SubQueryFieldEntry& sqe) { + try { + queryResultsHolder.resize(queryResultsHolder.size() + 1); + mainQuery.SetEntry( + i, std::move(mainQuery.GetUpdatableEntry(i)).FieldName(), sqe.Condition(), + selectSubQuery(mainQuery.GetSubQuery(sqe.QueryIndex()), mainQuery, locks, queryResultsHolder.back(), func, ctx)); + } catch (const Error& err) { + throw Error(err.code(), "Error during preprocessing of subquery '" + mainQuery.GetSubQuery(sqe.QueryIndex()).GetSQL() + + "': " + err.what()); + } + }); + } +} + +template void RxSelector::DoSelect>( + const Query&, QueryResults&, NsLocker&, SelectFunctionsHolder&, const RdxContext&, + QueryStatCalculator, long_actions::Logger>&); + +} // namespace reindexer diff --git a/cpp_src/core/reindexer_impl/rx_selector.h b/cpp_src/core/reindexer_impl/rx_selector.h new file mode 100644 index 000000000..d77e9c5e9 --- /dev/null +++ b/cpp_src/core/reindexer_impl/rx_selector.h @@ -0,0 +1,97 @@ +#pragma once + +#include "core/namespace/namespaceimpl.h" +#include "core/querystat.h" + +namespace reindexer { + +class RxSelector { + struct NsLockerItem { + NsLockerItem(NamespaceImpl::Ptr ins = {}) noexcept : ns(std::move(ins)), count(1) {} + NamespaceImpl::Ptr ns; + NamespaceImpl::Locker::RLockT nsLck; + unsigned count = 1; + }; + +public: + template + class NsLocker : private h_vector { + public: + NsLocker(const Context &context) : context_(context) {} + ~NsLocker() { + // Unlock first + for (auto it = rbegin(); it != rend(); ++it) { + // Some of the namespaces may be in unlocked statet in case of the exception during Lock() call + if (it->nsLck.owns_lock()) { + it->nsLck.unlock(); + } else { + assertrx(!locked_); + } + } + // Clean (ns may releases, if locker holds last ref) + } + + void Add(NamespaceImpl::Ptr ns) { + assertrx(!locked_); + for (auto it = begin(); it != end(); ++it) { + if (it->ns.get() == ns.get()) { + ++(it->count); + return; + } + } + + emplace_back(std::move(ns)); + return; + } + void Delete(const NamespaceImpl::Ptr &ns) { + for (auto it = begin(); it != end(); ++it) { + if (it->ns.get() == ns.get()) { + if (!--(it->count)) erase(it); + return; + } + } + assertrx(0); + } + void Lock() { + boost::sort::pdqsort_branchless( + begin(), end(), [](const NsLockerItem &lhs, const NsLockerItem &rhs) noexcept { return lhs.ns.get() < rhs.ns.get(); }); + for (auto it = begin(), e = end(); it != e; ++it) { + it->nsLck = it->ns->rLock(context_); + } + locked_ = true; + } + + NamespaceImpl::Ptr Get(const std::string &name) { + for (auto it = begin(); it != end(); it++) { + if (iequals(it->ns->name_, name)) return it->ns; + } + return nullptr; + } + + protected: + bool locked_ = false; + const Context &context_; + }; + + template + static void DoSelect(const Query &q, QueryResults &result, NsLocker &locks, SelectFunctionsHolder &func, const RdxContext &ctx, + QueryStatCalculator &queryStatCalculator); + +private: + struct QueryResultsContext; + template + static JoinedSelectors prepareJoinedSelectors(const Query &q, QueryResults &result, NsLocker &locks, SelectFunctionsHolder &func, + std::vector &, const RdxContext &ctx); + template + static void preselectSubQueries(Query &mainQuery, std::vector &queryResultsHolder, NsLocker &, SelectFunctionsHolder &, + const RdxContext &); + template + [[nodiscard]] static bool selectSubQuery(const Query &subQuery, const Query &mainQuery, NsLocker &, SelectFunctionsHolder &, + const RdxContext &); + template + [[nodiscard]] static VariantArray selectSubQuery(const Query &subQuery, const Query &mainQuery, NsLocker &, QueryResults &, + SelectFunctionsHolder &, const RdxContext &); + static bool isPreResultValuesModeOptimizationAvailable(const Query &jItemQ, const NamespaceImpl::Ptr &jns, const Query &mainQ); +}; + +} // namespace reindexer diff --git a/cpp_src/core/selectfunc/nsselectfuncinterface.cc b/cpp_src/core/selectfunc/nsselectfuncinterface.cc index ba5c0c8ea..e5e470865 100644 --- a/cpp_src/core/selectfunc/nsselectfuncinterface.cc +++ b/cpp_src/core/selectfunc/nsselectfuncinterface.cc @@ -5,14 +5,14 @@ namespace reindexer { const std::string& NsSelectFuncInterface::GetName() const noexcept { return nm_.name_; }; int NsSelectFuncInterface::getIndexByName(std::string_view index) const noexcept { return nm_.getIndexByName(index); } -bool NsSelectFuncInterface::getIndexByName(std::string_view name, int& index) const noexcept { return nm_.getIndexByName(name, index); } +bool NsSelectFuncInterface::getIndexByName(std::string_view name, int& index) const noexcept { return nm_.tryGetIndexByName(name, index); } int NsSelectFuncInterface::getIndexesCount() const noexcept { return nm_.indexes_.size(); } const std::string& NsSelectFuncInterface::getIndexName(int id) const noexcept { return nm_.indexes_[id]->Name(); } IndexType NsSelectFuncInterface::getIndexType(int id) const noexcept { return nm_.indexes_[id]->Type(); } const FieldsSet& NsSelectFuncInterface::getIndexFields(int id) const noexcept { return nm_.indexes_[id]->Fields(); } TagsPath NsSelectFuncInterface::getTagsPathForField(std::string_view jsonPath) const noexcept { - return nm_.tagsMatcher_.path2tag(jsonPath); + return nm_.tagsMatcher_.path2tag(jsonPath); } } // namespace reindexer diff --git a/cpp_src/core/selectfunc/selectfunc.cc b/cpp_src/core/selectfunc/selectfunc.cc index 604571816..58ae7c734 100644 --- a/cpp_src/core/selectfunc/selectfunc.cc +++ b/cpp_src/core/selectfunc/selectfunc.cc @@ -38,7 +38,7 @@ SelectFunction::Ptr SelectFunctionsHolder::AddNamespace(const Query &q, const Na return queries_[nsid]; } -SelectFunction::SelectFunction(const Query &q, NsSelectFuncInterface &&nm) : nm_(std::move(nm)), currCjsonFieldIdx_(nm.getIndexesCount()) { +SelectFunction::SelectFunction(const Query &q, NsSelectFuncInterface &&nm) : nm_(std::move(nm)), currCjsonFieldIdx_(nm_.getIndexesCount()) { functions_.reserve(q.selectFunctions_.size()); for (auto &func : q.selectFunctions_) { SelectFuncParser parser; diff --git a/cpp_src/core/selectkeyresult.h b/cpp_src/core/selectkeyresult.h index 17a597eb0..55f83498b 100644 --- a/cpp_src/core/selectkeyresult.h +++ b/cpp_src/core/selectkeyresult.h @@ -199,18 +199,20 @@ class SelectKeyResult : public h_vector { size_t actualSize = 0; ids.resize(idsCount); auto rit = ids.begin(); - for (auto it = begin(); it != end(); ++it) { + for (auto it = begin(), endIt = end(); it != endIt; ++it) { if (it->isRange_) { throw Error(errLogic, "Unable to merge 'range' idset ('generic sort mode')"); } if (it->useBtree_) { - actualSize += it->set_->size(); + const auto sz = it->set_->size(); + actualSize += sz; std::copy(it->set_->begin(), it->set_->end(), rit); - rit += it->set_->size(); + rit += sz; } else { - actualSize += it->ids_.size(); + const auto sz = it->ids_.size(); + actualSize += sz; std::copy(it->ids_.begin(), it->ids_.end(), rit); - rit += it->ids_.size(); + rit += sz; } } assertrx(idsCount == actualSize); @@ -218,7 +220,7 @@ class SelectKeyResult : public h_vector { } else { mergedIds = make_intrusive>(); mergedIds->reserve(idsCount); - for (auto it = begin(); it != end(); ++it) { + for (auto it = begin(), endIt = end(); it != endIt; ++it) { if (it->isRange_) { throw Error(errLogic, "Unable to merge 'range' idset ('merge sort mode')"); } @@ -231,7 +233,7 @@ class SelectKeyResult : public h_vector { for (;;) { const int min = mergedIds->size() ? mergedIds->back() : INT_MIN; int curMin = INT_MAX; - for (auto it = begin(); it != end(); it++) { + for (auto it = begin(), endIt = end(); it != endIt; ++it) { if (it->useBtree_) { const auto end = it->set_->end(); for (; it->itset_ != end && *it->itset_ <= min; ++it->itset_) { @@ -250,8 +252,8 @@ class SelectKeyResult : public h_vector { mergedIds->shrink_to_fit(); } clear(); - emplace_back(SingleSelectKeyResult(mergedIds)); deferedExplicitSort = false; + emplace_back(mergedIds); return mergedIds; } }; diff --git a/cpp_src/core/transaction.cc b/cpp_src/core/transaction.cc index fc39bad7f..83f881da4 100644 --- a/cpp_src/core/transaction.cc +++ b/cpp_src/core/transaction.cc @@ -40,6 +40,14 @@ void Transaction::Modify(Query &&query) { if (impl_) impl_->Modify(std::move(query)); } +void Transaction::PutMeta(std::string_view key, std::string_view value) { + if (impl_) impl_->PutMeta(key, value); +} + +void Transaction::SetTagsMatcher(TagsMatcher &&tm) { + if (impl_) impl_->SetTagsMatcher(std::move(tm)); +} + Item Transaction::NewItem() { return impl_->NewItem(); } std::vector &Transaction::GetSteps() { diff --git a/cpp_src/core/transaction.h b/cpp_src/core/transaction.h index 0ab5c8b43..27709df4f 100644 --- a/cpp_src/core/transaction.h +++ b/cpp_src/core/transaction.h @@ -29,6 +29,8 @@ class Transaction { void Delete(Item &&item); void Modify(Item &&item, ItemModifyMode mode); void Modify(Query &&query); + void PutMeta(std::string_view key, std::string_view value); + void SetTagsMatcher(TagsMatcher &&tm); bool IsFree() { return impl_ == nullptr; } Item NewItem(); Item GetItem(TransactionStep &&st); diff --git a/cpp_src/core/transactionimpl.cc b/cpp_src/core/transactionimpl.cc index a7ccb4f16..e5c8e8853 100644 --- a/cpp_src/core/transactionimpl.cc +++ b/cpp_src/core/transactionimpl.cc @@ -7,18 +7,41 @@ namespace reindexer { void TransactionImpl::checkTagsMatcher(Item &item) { if (item.IsTagsUpdated()) { ItemImpl *ritem = item.impl_; - UpdateTagsMatcherFromItem(ritem); + if (ritem->Type().get() != payloadType_.get() || !tagsMatcher_.try_merge(ritem->tagsMatcher())) { + std::string jsonSliceBuf(ritem->GetJSON()); + + ItemImpl tmpItem(payloadType_, tagsMatcher_); + tmpItem.Value().SetLSN(ritem->Value().GetLSN()); + *ritem = std::move(tmpItem); + + auto err = ritem->FromJSON(jsonSliceBuf, nullptr); + if (!err.ok()) throw err; + + if (ritem->tagsMatcher().isUpdated() && !tagsMatcher_.try_merge(ritem->tagsMatcher())) + throw Error(errLogic, "Could not insert item. TagsMatcher was not merged."); + ritem->tagsMatcher() = tagsMatcher_; + ritem->tagsMatcher().setUpdated(); + } else { + ritem->tagsMatcher() = tagsMatcher_; + ritem->tagsMatcher().setUpdated(); + } tagsUpdated_ = true; } } Item TransactionImpl::NewItem() { std::unique_lock lock(mtx_); - return Item(new ItemImpl(payloadType_, tagsMatcher_, pkFields_)); + Item item(new ItemImpl(payloadType_, tagsMatcher_, pkFields_)); + item.impl_->tagsMatcher().clearUpdated(); + return item; } + Item TransactionImpl::GetItem(TransactionStep &&st) { std::unique_lock lock(mtx_); - return Item(new ItemImpl(payloadType_, tagsMatcher_, pkFields_, schema_, std::move(st.itemData_))); + auto &data = std::get(st.data_); + auto item = Item(new ItemImpl(payloadType_, tagsMatcher_, pkFields_, schema_, std::move(data.data))); + data.hadTmUpdate ? item.impl_->tagsMatcher().setUpdated() : item.impl_->tagsMatcher().clearUpdated(); + return item; } void TransactionImpl::ValidatePK(const FieldsSet &pkFields) { @@ -30,58 +53,57 @@ void TransactionImpl::ValidatePK(const FieldsSet &pkFields) { } } -void TransactionImpl::UpdateTagsMatcherFromItem(ItemImpl *ritem) { - if (ritem->Type().get() != payloadType_.get() || (ritem->tagsMatcher().isUpdated() && !tagsMatcher_.try_merge(ritem->tagsMatcher()))) { - std::string jsonSliceBuf(ritem->GetJSON()); - - ItemImpl tmpItem(payloadType_, tagsMatcher_); - tmpItem.Value().SetLSN(ritem->Value().GetLSN()); - *ritem = std::move(tmpItem); - - auto err = ritem->FromJSON(jsonSliceBuf, nullptr); - if (!err.ok()) throw err; - - if (ritem->tagsMatcher().isUpdated() && !tagsMatcher_.try_merge(ritem->tagsMatcher())) - throw Error(errLogic, "Could not insert item. TagsMatcher was not merged."); - ritem->tagsMatcher() = tagsMatcher_; - ritem->tagsMatcher().setUpdated(); - } - if (ritem->tagsMatcher().isUpdated()) { - ritem->tagsMatcher() = tagsMatcher_; - ritem->tagsMatcher().setUpdated(); - } -} - void TransactionImpl::Insert(Item &&item) { std::unique_lock lock(mtx_); checkTagsMatcher(item); - steps_.emplace_back(TransactionStep{std::move(item), ModeInsert}); + steps_.emplace_back(std::move(item), ModeInsert); } void TransactionImpl::Update(Item &&item) { std::unique_lock lock(mtx_); checkTagsMatcher(item); - steps_.emplace_back(TransactionStep{std::move(item), ModeUpdate}); + steps_.emplace_back(std::move(item), ModeUpdate); } void TransactionImpl::Upsert(Item &&item) { std::unique_lock lock(mtx_); checkTagsMatcher(item); - steps_.emplace_back(TransactionStep{std::move(item), ModeUpsert}); + steps_.emplace_back(std::move(item), ModeUpsert); } void TransactionImpl::Delete(Item &&item) { std::unique_lock lock(mtx_); checkTagsMatcher(item); - steps_.emplace_back(TransactionStep{std::move(item), ModeDelete}); + steps_.emplace_back(std::move(item), ModeDelete); } void TransactionImpl::Modify(Item &&item, ItemModifyMode mode) { std::unique_lock lock(mtx_); checkTagsMatcher(item); hasDeleteItemSteps_ = hasDeleteItemSteps_ || (mode == ModeDelete); - steps_.emplace_back(TransactionStep{std::move(item), mode}); + steps_.emplace_back(std::move(item), mode); } void TransactionImpl::Modify(Query &&query) { std::unique_lock lock(mtx_); - steps_.emplace_back(TransactionStep(std::move(query))); + steps_.emplace_back(std::move(query)); +} + +void TransactionImpl::PutMeta(std::string_view key, std::string_view value) { + if (key.empty()) { + throw Error(errLogic, "Empty meta key is not allowed in tx"); + } + + std::lock_guard lock(mtx_); + steps_.emplace_back(key, value); +} + +void TransactionImpl::SetTagsMatcher(TagsMatcher &&tm) { + std::lock_guard lock(mtx_); + // NOTE: In v4 tm tokens here are always the same, but in v3 those tokens are not synchronized. Probably it should workd anyway + // if (tm.stateToken() != tagsMatcher_.stateToken()) { + // throw Error(errParams, "Tx tm statetoken missmatch: %08X vs %08X", tagsMatcher_.stateToken(), tm.stateToken()); + // } + tagsMatcher_ = tm; + tagsMatcher_.UpdatePayloadType(payloadType_, false); + tagsUpdated_ = true; + steps_.emplace_back(std::move(tm)); } } // namespace reindexer diff --git a/cpp_src/core/transactionimpl.h b/cpp_src/core/transactionimpl.h index 89baa10d9..36403c28e 100644 --- a/cpp_src/core/transactionimpl.h +++ b/cpp_src/core/transactionimpl.h @@ -5,22 +5,46 @@ namespace reindexer { +struct TransactionItemStep { + ItemModifyMode mode; + bool hadTmUpdate; + ItemImplRawData data; +}; + +struct TransactionQueryStep { + std::unique_ptr query; +}; + +struct TransactionMetaStep { + std::string key; + std::string value; +}; + +struct TransactionTmStep { + TagsMatcher tm; +}; + class TransactionStep { public: - TransactionStep(Item &&item, ItemModifyMode modifyMode) : itemData_(std::move(*item.impl_)), modifyMode_(modifyMode), query_(nullptr) { + enum class Type : uint8_t { Nop, ModifyItem, Query, PutMeta, SetTM }; + + TransactionStep(Item &&item, ItemModifyMode modifyMode) + : data_(TransactionItemStep{modifyMode, item.IsTagsUpdated(), std::move(*item.impl_)}), type_(Type::ModifyItem) { delete item.impl_; item.impl_ = nullptr; } - TransactionStep(Query &&query) : modifyMode_(ModeUpdate), query_(new Query(std::move(query))) {} + TransactionStep(TagsMatcher &&tm) : data_(TransactionTmStep{std::move(tm)}), type_(Type::SetTM) {} + TransactionStep(Query &&query) : data_(TransactionQueryStep{std::make_unique(std::move(query))}), type_(Type::Query) {} + TransactionStep(std::string_view key, std::string_view value) + : data_(TransactionMetaStep{std::string(key), std::string(value)}), type_(Type::PutMeta) {} TransactionStep(const TransactionStep &) = delete; TransactionStep &operator=(const TransactionStep &) = delete; - TransactionStep(TransactionStep && /*rhs*/) noexcept = default; - TransactionStep &operator=(TransactionStep && /*rhs*/) = default; + TransactionStep(TransactionStep && /*rhs*/) = default; + TransactionStep &operator=(TransactionStep && /*rhs*/) = delete; - ItemImplRawData itemData_; - ItemModifyMode modifyMode_; - std::unique_ptr query_; + std::variant data_; + Type type_; }; class TransactionImpl { @@ -34,7 +58,9 @@ class TransactionImpl { nsName_(nsName), tagsUpdated_(false), hasDeleteItemSteps_(false), - startTime_(std::chrono::high_resolution_clock::now()) {} + startTime_(std::chrono::high_resolution_clock::now()) { + tagsMatcher_.clearUpdated(); + } void Insert(Item &&item); void Update(Item &&item); @@ -42,8 +68,9 @@ class TransactionImpl { void Delete(Item &&item); void Modify(Item &&item, ItemModifyMode mode); void Modify(Query &&item); + void PutMeta(std::string_view key, std::string_view value); + void SetTagsMatcher(TagsMatcher &&tm); - void UpdateTagsMatcherFromItem(ItemImpl *ritem); Item NewItem(); Item GetItem(TransactionStep &&st); void ValidatePK(const FieldsSet &pkFields); diff --git a/cpp_src/core/type_consts.h b/cpp_src/core/type_consts.h index 131d8a2db..06463ce22 100644 --- a/cpp_src/core/type_consts.h +++ b/cpp_src/core/type_consts.h @@ -68,6 +68,9 @@ typedef enum QueryItemType { QueryUpdateFieldV2 = 25, QueryBetweenFieldsCondition = 26, QueryAlwaysFalseCondition = 27, + QueryAlwaysTrueCondition = 28, + QuerySubQueryCondition = 29, + QueryFieldSubQueryCondition = 30, } QueryItemType; typedef enum QuerySerializeMode { diff --git a/cpp_src/core/type_consts_helpers.h b/cpp_src/core/type_consts_helpers.h index d4d32897e..fa78bdd50 100644 --- a/cpp_src/core/type_consts_helpers.h +++ b/cpp_src/core/type_consts_helpers.h @@ -72,6 +72,19 @@ auto& operator<<(T& os, OpType op) { std::abort(); } +inline std::string_view OpTypeToStr(OpType op) { + using namespace std::string_view_literals; + switch (op) { + case OpOr: + return "OR"sv; + case OpAnd: + return "AND"sv; + case OpNot: + return "NOT"sv; + } + std::abort(); +} + template auto& operator<<(T& os, JoinType jt) { return os << JoinTypeName(jt); diff --git a/cpp_src/debug/terminate_handler.cpp b/cpp_src/debug/terminate_handler.cpp index 7269ccde5..b2a365d56 100644 --- a/cpp_src/debug/terminate_handler.cpp +++ b/cpp_src/debug/terminate_handler.cpp @@ -30,6 +30,7 @@ static void terminate_handler() { } catch (Error &err) { sout << ": " << err.what(); } catch (...) { + sout << ": "; } sout << " ***" << std::endl; } else { diff --git a/cpp_src/estl/contexted_locks.h b/cpp_src/estl/contexted_locks.h index ba8dc9045..2e60b0ec8 100644 --- a/cpp_src/estl/contexted_locks.h +++ b/cpp_src/estl/contexted_locks.h @@ -13,32 +13,27 @@ using std::adopt_lock_t; namespace reindexer { -const milliseconds kDefaultCondChkTime = milliseconds(20); +constexpr milliseconds kDefaultCondChkTime = milliseconds(20); template class contexted_unique_lock { public: using MutexType = _Mutex; - explicit contexted_unique_lock() : _M_mtx(nullptr), _M_owns(false), _M_context(nullptr), _M_chkTimeout(kDefaultCondChkTime) {} - explicit contexted_unique_lock(MutexType& __mtx, Context* __context, milliseconds __chkTimeout = kDefaultCondChkTime) - : _M_mtx(&__mtx), _M_owns(false), _M_context(__context), _M_chkTimeout(__chkTimeout) { - assertrx(_M_context); + explicit contexted_unique_lock() noexcept : _M_mtx(nullptr), _M_owns(false), _M_context(nullptr), _M_chkTimeout(kDefaultCondChkTime) {} + explicit contexted_unique_lock(MutexType& __mtx, Context& __context, milliseconds __chkTimeout = kDefaultCondChkTime) + : _M_mtx(&__mtx), _M_owns(false), _M_context(&__context), _M_chkTimeout(__chkTimeout) { lock(); } - explicit contexted_unique_lock(MutexType& __mtx, defer_lock_t, Context* __context, milliseconds __chkTimeout = kDefaultCondChkTime) - : _M_mtx(&__mtx), _M_owns(false), _M_context(__context), _M_chkTimeout(__chkTimeout) { - assertrx(_M_context); - } - explicit contexted_unique_lock(MutexType& __mtx, adopt_lock_t, Context* __context, milliseconds __chkTimeout = kDefaultCondChkTime) - : _M_mtx(&__mtx), _M_owns(true), _M_context(__context), _M_chkTimeout(__chkTimeout) { - assertrx(_M_context); - } - explicit contexted_unique_lock(MutexType& __mtx, try_to_lock_t, Context* __context, milliseconds __chkTimeout = kDefaultCondChkTime) - : _M_mtx(&__mtx), _M_owns(__mtx.try_lock()), _M_context(__context), _M_chkTimeout(__chkTimeout) { - assertrx(_M_context); - } - contexted_unique_lock(contexted_unique_lock&& lck) + explicit contexted_unique_lock(MutexType& __mtx, defer_lock_t, Context& __context, + milliseconds __chkTimeout = kDefaultCondChkTime) noexcept + : _M_mtx(&__mtx), _M_owns(false), _M_context(&__context), _M_chkTimeout(__chkTimeout) {} + explicit contexted_unique_lock(MutexType& __mtx, adopt_lock_t, Context& __context, + milliseconds __chkTimeout = kDefaultCondChkTime) noexcept + : _M_mtx(&__mtx), _M_owns(true), _M_context(&__context), _M_chkTimeout(__chkTimeout) {} + explicit contexted_unique_lock(MutexType& __mtx, try_to_lock_t, Context& __context, milliseconds __chkTimeout = kDefaultCondChkTime) + : _M_mtx(&__mtx), _M_owns(__mtx.try_lock()), _M_context(&__context), _M_chkTimeout(__chkTimeout) {} + contexted_unique_lock(contexted_unique_lock&& lck) noexcept : _M_mtx(lck._M_mtx), _M_owns(lck._M_owns), _M_context(lck._M_context), _M_chkTimeout(lck._M_chkTimeout) { lck._M_owns = false; lck._M_mtx = nullptr; @@ -50,7 +45,7 @@ class contexted_unique_lock { contexted_unique_lock(const contexted_unique_lock&) = delete; contexted_unique_lock& operator=(const contexted_unique_lock&) = delete; - contexted_unique_lock& operator=(contexted_unique_lock&& lck) { + contexted_unique_lock& operator=(contexted_unique_lock&& lck) noexcept { if (this != &lck) { if (_M_owns) unlock(); _M_mtx = lck._M_mtx; @@ -102,7 +97,7 @@ class contexted_unique_lock { MutexType* mutex() const noexcept { return _M_mtx; } private: - void _M_lockable() const { + void _M_lockable() const noexcept { if (_M_mtx == nullptr) assertrx(0); if (_M_owns) assertrx(0); } @@ -118,21 +113,17 @@ class contexted_shared_lock { public: using MutexType = _Mutex; - explicit contexted_shared_lock() : _M_mtx(nullptr), _M_owns(false), _M_context(nullptr), _M_chkTimeout(kDefaultCondChkTime) {} - explicit contexted_shared_lock(MutexType& __mtx, Context* __context, milliseconds __chkTimeout = kDefaultCondChkTime) - : _M_mtx(&__mtx), _M_owns(false), _M_context(__context), _M_chkTimeout(__chkTimeout) { - assertrx(_M_context); + explicit contexted_shared_lock() noexcept : _M_mtx(nullptr), _M_owns(false), _M_context(nullptr), _M_chkTimeout(kDefaultCondChkTime) {} + explicit contexted_shared_lock(MutexType& __mtx, Context& __context, milliseconds __chkTimeout = kDefaultCondChkTime) + : _M_mtx(&__mtx), _M_owns(false), _M_context(&__context), _M_chkTimeout(__chkTimeout) { lock(); } - explicit contexted_shared_lock(MutexType& __mtx, adopt_lock_t, Context* __context, milliseconds __chkTimeout = kDefaultCondChkTime) - : _M_mtx(&__mtx), _M_owns(true), _M_context(__context), _M_chkTimeout(__chkTimeout) { - assertrx(_M_context); - } - explicit contexted_shared_lock(MutexType& __mtx, try_to_lock_t, Context* __context, milliseconds __chkTimeout = kDefaultCondChkTime) - : _M_mtx(&__mtx), _M_owns(__mtx.try_lock()), _M_context(__context), _M_chkTimeout(__chkTimeout) { - assertrx(_M_context); - } - contexted_shared_lock(contexted_shared_lock&& lck) + explicit contexted_shared_lock(MutexType& __mtx, adopt_lock_t, Context& __context, + milliseconds __chkTimeout = kDefaultCondChkTime) noexcept + : _M_mtx(&__mtx), _M_owns(true), _M_context(&__context), _M_chkTimeout(__chkTimeout) {} + explicit contexted_shared_lock(MutexType& __mtx, try_to_lock_t, Context& __context, milliseconds __chkTimeout = kDefaultCondChkTime) + : _M_mtx(&__mtx), _M_owns(__mtx.try_lock()), _M_context(&__context), _M_chkTimeout(__chkTimeout) {} + contexted_shared_lock(contexted_shared_lock&& lck) noexcept : _M_mtx(lck._M_mtx), _M_owns(lck._M_owns), _M_context(lck._M_context), _M_chkTimeout(lck._M_chkTimeout) { lck._M_owns = false; lck._M_mtx = nullptr; @@ -144,7 +135,7 @@ class contexted_shared_lock { contexted_shared_lock(const contexted_shared_lock&) = delete; contexted_shared_lock& operator=(const contexted_shared_lock&) = delete; - contexted_shared_lock& operator=(contexted_shared_lock&& lck) { + contexted_shared_lock& operator=(contexted_shared_lock&& lck) noexcept { if (this != &lck) { if (_M_owns) unlock(); _M_mtx = lck._M_mtx; @@ -196,7 +187,7 @@ class contexted_shared_lock { MutexType* mutex() const noexcept { return _M_mtx; } private: - void _M_lockable() const { + void _M_lockable() const noexcept { if (_M_mtx == nullptr) assertrx(0); if (_M_owns) assertrx(0); } diff --git a/cpp_src/estl/h_vector.h b/cpp_src/estl/h_vector.h index 1f26945d3..735ce3f55 100644 --- a/cpp_src/estl/h_vector.h +++ b/cpp_src/estl/h_vector.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "debug_macros.h" #include "trivial_reverse_iterator.h" @@ -123,7 +124,7 @@ class h_vector { return *this; } - bool operator==(const h_vector& other) const noexcept { + bool operator==(const h_vector& other) const noexcept(noexcept(std::declval() == std::declval())) { if (&other != this) { if (size() != other.size()) return false; for (size_t i = 0; i < size(); ++i) { @@ -133,7 +134,9 @@ class h_vector { } return true; } - bool operator!=(const h_vector& other) const noexcept { return !operator==(other); } + bool operator!=(const h_vector& other) const noexcept(noexcept(std::declval() == std::declval())) { + return !operator==(other); + } template void clear() noexcept { diff --git a/cpp_src/estl/suffix_map.h b/cpp_src/estl/suffix_map.h index 37864d4cf..18ae3e179 100644 --- a/cpp_src/estl/suffix_map.h +++ b/cpp_src/estl/suffix_map.h @@ -203,6 +203,6 @@ class suffix_map { std::vector mapped_; std::vector text_; bool built_ = false; -}; // namespace reindexer +}; } // namespace reindexer diff --git a/cpp_src/estl/tokenizer.cc b/cpp_src/estl/tokenizer.cc index ba3e27f75..d4d69bd87 100644 --- a/cpp_src/estl/tokenizer.cc +++ b/cpp_src/estl/tokenizer.cc @@ -16,8 +16,9 @@ void tokenizer::skip_space() noexcept { cur_++; pos_++; } - } else + } else { return; + } } } diff --git a/cpp_src/estl/tokenizer.h b/cpp_src/estl/tokenizer.h index 399083e19..b6904a372 100644 --- a/cpp_src/estl/tokenizer.h +++ b/cpp_src/estl/tokenizer.h @@ -13,8 +13,8 @@ class token { token(token_type t = TokenSymbol) noexcept : type(t) {} token(const token &) = delete; token &operator=(const token &) = delete; - token(token &&other) = default; - token &operator=(token &&other) = default; + token(token &&) noexcept = default; + token &operator=(token &&) noexcept = default; std::string_view text() const noexcept { return std::string_view(text_.data(), text_.size()); } void to_lower() noexcept { @@ -45,7 +45,7 @@ class tokenizer { tokenizer(std::string_view query) noexcept : q_(query), cur_(query.begin()) {} token next_token(flags f = flags(flags::to_lower)); - token peek_token(flags f = flags(flags::to_lower)) { + [[nodiscard]] token peek_token(flags f = flags(flags::to_lower)) { auto save_cur = cur_; auto save_pos = pos_; auto res = next_token(f); @@ -53,6 +53,17 @@ class tokenizer { pos_ = save_pos; return res; } + [[nodiscard]] token peek_second_token(flags f = flags(flags::to_lower)) { + auto save_cur = cur_; + auto save_pos = pos_; + auto res = next_token(f); + if (res.type != TokenEnd) { + res = next_token(f); + } + cur_ = save_cur; + pos_ = save_pos; + return res; + } void skip_space() noexcept; bool end() const noexcept { return cur_ == q_.end(); } size_t getPos() const noexcept { return pos_; } @@ -65,7 +76,7 @@ class tokenizer { size_t length() const noexcept { return q_.length(); } const char *begin() const noexcept { return q_.data(); } -protected: +private: std::string_view q_; std::string_view::const_iterator cur_; size_t pos_ = 0; diff --git a/cpp_src/gtests/bench/fixtures/api_tv_simple.cc b/cpp_src/gtests/bench/fixtures/api_tv_simple.cc index e628e2b5f..7c8cec8b9 100644 --- a/cpp_src/gtests/bench/fixtures/api_tv_simple.cc +++ b/cpp_src/gtests/bench/fixtures/api_tv_simple.cc @@ -81,9 +81,9 @@ void ApiTvSimple::RegisterAllCases() { Register("Query2CondLeftJoin", &ApiTvSimple::Query2CondLeftJoin, this); Register("Query2CondLeftJoinTotal", &ApiTvSimple::Query2CondLeftJoinTotal, this); Register("Query2CondLeftJoinCachedTotal", &ApiTvSimple::Query2CondLeftJoinCachedTotal, this); - Register("Query0CondInnerJoinUnlimit", &ApiTvSimple::Query0CondInnerJoinUnlimit, this); - Register("Query0CondInnerJoinUnlimitLowSelectivity", &ApiTvSimple::Query0CondInnerJoinUnlimitLowSelectivity, this); - Register("Query0CondInnerJoinPreResultStoreValues", &ApiTvSimple::Query0CondInnerJoinPreResultStoreValues, this); + Register("Query0CondInnerJoinUnlimit", &ApiTvSimple::Query0CondInnerJoinUnlimit, this)->Iterations(500); + Register("Query0CondInnerJoinUnlimitLowSelectivity", &ApiTvSimple::Query0CondInnerJoinUnlimitLowSelectivity, this)->Iterations(500); + Register("Query0CondInnerJoinPreResultStoreValues", &ApiTvSimple::Query0CondInnerJoinPreResultStoreValues, this)->Iterations(500); Register("Query2CondInnerJoin", &ApiTvSimple::Query2CondInnerJoin, this); Register("Query2CondInnerJoinTotal", &ApiTvSimple::Query2CondInnerJoinTotal, this); Register("Query2CondInnerJoinCachedTotal", &ApiTvSimple::Query2CondInnerJoinCachedTotal, this); @@ -95,9 +95,9 @@ void ApiTvSimple::RegisterAllCases() { Register("Query4Cond", &ApiTvSimple::Query4Cond, this); Register("Query4CondTotal", &ApiTvSimple::Query4CondTotal, this); Register("Query4CondCachedTotal", &ApiTvSimple::Query4CondCachedTotal, this); - Register("Query4CondRange", &ApiTvSimple::Query4CondRange, this); - Register("Query4CondRangeTotal", &ApiTvSimple::Query4CondRangeTotal, this); - Register("Query4CondRangeCachedTotal", &ApiTvSimple::Query4CondRangeCachedTotal, this); + Register("Query4CondRange", &ApiTvSimple::Query4CondRange, this)->Iterations(1000); + Register("Query4CondRangeTotal", &ApiTvSimple::Query4CondRangeTotal, this)->Iterations(1000); + Register("Query4CondRangeCachedTotal", &ApiTvSimple::Query4CondRangeCachedTotal, this)->Iterations(1000); #if !defined(REINDEX_WITH_ASAN) && !defined(REINDEX_WITH_TSAN) && !defined(RX_WITH_STDLIB_DEBUG) Register("Query2CondIdSet10", &ApiTvSimple::Query2CondIdSet10, this); #endif // !defined(REINDEX_WITH_ASAN) && !defined(REINDEX_WITH_TSAN) @@ -111,7 +111,12 @@ void ApiTvSimple::RegisterAllCases() { Register("FromCJSONPKOnly", &ApiTvSimple::FromCJSONPKOnly, this); Register("GetCJSON", &ApiTvSimple::GetCJSON, this); Register("ExtractField", &ApiTvSimple::ExtractField, this); - // NOLINTEND(*cplusplus.NewDeleteLeaks) + + // Those benches should be last, because they are recreating indexes cache + Register("Query4CondRangeDropCache", &ApiTvSimple::Query4CondRangeDropCache, this)->Iterations(1000); + Register("Query4CondRangeDropCacheTotal", &ApiTvSimple::Query4CondRangeDropCacheTotal, this)->Iterations(1000); + Register("Query4CondRangeDropCacheCachedTotal", &ApiTvSimple::Query4CondRangeDropCacheCachedTotal, this)->Iterations(1000); + // NOLINTEND(*cplusplus.NewDeleteLeaks) } reindexer::Error ApiTvSimple::Initialize() { @@ -142,6 +147,7 @@ reindexer::Error ApiTvSimple::Initialize() { uuids_.emplace_back(randStrUuid()); } + devices_ = {"iphone", "android", "smarttv", "stb", "ottstb"}; locations_ = {"mos", "ct", "dv", "sth", "vlg", "sib", "ural"}; for (int i = 0; i < 10; i++) packages_.emplace_back(randomNumArray(20, 10000, 10)); @@ -774,18 +780,25 @@ void ApiTvSimple::Query2CondLeftJoinCachedTotal(benchmark::State& state) { void ApiTvSimple::Query0CondInnerJoinUnlimit(benchmark::State& state) { AllocsTracker allocsTracker(state); + size_t num = 0; for (auto _ : state) { // NOLINT(*deadcode.DeadStores) Query q4join("JoinItems"); Query q(nsdef_.name); q.ReqTotal().Limit(1); - q4join.Where("device", CondEq, "ottstb").Where("location", CondEq, "mos"); + // Results depend on the joined query expected results size. If preselect is disabled, then + // timing will be much higher. To stabilize benchmark result we are using all combinations of 'device' and 'location' + size_t deviceId = num % devices_.size(); + size_t locationId = (num / devices_.size()) % locations_.size(); + + q4join.Where("device", CondEq, devices_[deviceId]).Where("location", CondEq, locations_[locationId]); q.InnerJoin("price_id", "id", CondSet, std::move(q4join)); QueryResults qres; auto err = db_->Select(q, qres); if (!err.ok()) state.SkipWithError(err.what().c_str()); + ++num; } } @@ -1064,7 +1077,7 @@ void ApiTvSimple::Query4CondCachedTotal(benchmark::State& state) { void ApiTvSimple::Query4CondRange(benchmark::State& state) { AllocsTracker allocsTracker(state); for (auto _ : state) { // NOLINT(*deadcode.DeadStores) - int startTime = random(0, 50000); + int startTime = random(0, 30000); int endTime = startTime + 10000; Query q(nsdef_.name); q.Limit(20) @@ -1083,7 +1096,7 @@ void ApiTvSimple::Query4CondRange(benchmark::State& state) { void ApiTvSimple::Query4CondRangeTotal(benchmark::State& state) { AllocsTracker allocsTracker(state); for (auto _ : state) { // NOLINT(*deadcode.DeadStores) - int startTime = random(0, 50000); + int startTime = random(0, 30000); int endTime = startTime + 10000; Query q(nsdef_.name); q.Limit(20) @@ -1103,7 +1116,72 @@ void ApiTvSimple::Query4CondRangeTotal(benchmark::State& state) { void ApiTvSimple::Query4CondRangeCachedTotal(benchmark::State& state) { AllocsTracker allocsTracker(state); for (auto _ : state) { // NOLINT(*deadcode.DeadStores) - int startTime = random(0, 50000); + int startTime = random(0, 30000); + int endTime = startTime + 10000; + Query q(nsdef_.name); + q.Limit(20) + .Sort("year", false) + .Where("genre", CondEq, 5) + .Where("year", CondRange, {2010, 2016}) + .Where("start_time", CondGt, startTime) + .Where("end_time", CondLt, endTime) + .CachedTotal(); + + QueryResults qres; + auto err = db_->Select(q, qres); + if (!err.ok()) state.SkipWithError(err.what().c_str()); + } +} + +void ApiTvSimple::Query4CondRangeDropCache(benchmark::State& state) { + IndexCacheSetter cacheDropper(*db_); + + AllocsTracker allocsTracker(state); + for (auto _ : state) { // NOLINT(*deadcode.DeadStores) + int startTime = random(0, 30000); + int endTime = startTime + 10000; + Query q(nsdef_.name); + q.Limit(20) + .Sort("year", false) + .Where("genre", CondEq, 5) + .Where("year", CondRange, {2010, 2016}) + .Where("start_time", CondGt, startTime) + .Where("end_time", CondLt, endTime); + + QueryResults qres; + auto err = db_->Select(q, qres); + if (!err.ok()) state.SkipWithError(err.what().c_str()); + } +} + +void ApiTvSimple::Query4CondRangeDropCacheTotal(benchmark::State& state) { + IndexCacheSetter cacheDropper(*db_); + + AllocsTracker allocsTracker(state); + for (auto _ : state) { // NOLINT(*deadcode.DeadStores) + int startTime = random(0, 30000); + int endTime = startTime + 10000; + Query q(nsdef_.name); + q.Limit(20) + .Sort("year", false) + .Where("genre", CondEq, 5) + .Where("year", CondRange, {2010, 2016}) + .Where("start_time", CondGt, startTime) + .Where("end_time", CondLt, endTime) + .ReqTotal(); + + QueryResults qres; + auto err = db_->Select(q, qres); + if (!err.ok()) state.SkipWithError(err.what().c_str()); + } +} + +void ApiTvSimple::Query4CondRangeDropCacheCachedTotal(benchmark::State& state) { + IndexCacheSetter cacheDropper(*db_); + + AllocsTracker allocsTracker(state); + for (auto _ : state) { // NOLINT(*deadcode.DeadStores) + int startTime = random(0, 30000); int endTime = startTime + 10000; Query q(nsdef_.name); q.Limit(20) diff --git a/cpp_src/gtests/bench/fixtures/api_tv_simple.h b/cpp_src/gtests/bench/fixtures/api_tv_simple.h index 45b9a0d4c..97a0362d2 100644 --- a/cpp_src/gtests/bench/fixtures/api_tv_simple.h +++ b/cpp_src/gtests/bench/fixtures/api_tv_simple.h @@ -28,6 +28,43 @@ class ApiTvSimple : private BaseFixture { reindexer::Error Initialize() override; private: + class IndexCacheSetter { + public: + constexpr static unsigned kVeryLargeHitsValue = 1000000; + + IndexCacheSetter(reindexer::Reindexer& db, unsigned hitsCount = kVeryLargeHitsValue) : db_(db) { + shrinkCache(); + setHitsCount(hitsCount); + } + ~IndexCacheSetter() { setHitsCount(kDefaultCacheHits); } + + private: + constexpr static int64_t kDefaultCacheSize = 134217728; + constexpr static int64_t kDefaultCacheHits = 2; + + void shrinkCache() { + // Shrink cache size to force cache invalidation + auto q = reindexer::Query("#config").Set("namespaces.cache.index_idset_cache_size", 1024).Where("type", CondEq, "namespaces"); + reindexer::QueryResults qr; + auto err = db_.Update(q, qr); + assertrx(err.ok()); + assertrx(qr.Count() == 1); + } + void setHitsCount(unsigned hitsCount) { + // Set required hits count and default cache size + auto q = reindexer::Query("#config") + .Set("namespaces.cache.index_idset_cache_size", kDefaultCacheSize) + .Set("namespaces.cache.index_idset_hits_to_cache", int64_t(hitsCount)) + .Where("type", CondEq, "namespaces"); + reindexer::QueryResults qr; + auto err = db_.Update(q, qr); + assertrx(err.ok()); + assertrx(qr.Count() == 1); + } + + reindexer::Reindexer& db_; + }; + reindexer::Item MakeItem(benchmark::State&) override; reindexer::Item MakeStrItem(); @@ -83,6 +120,9 @@ class ApiTvSimple : private BaseFixture { void FromCJSONPKOnly(State&); void GetCJSON(State&); void ExtractField(State&); + void Query4CondRangeDropCache(State& state); + void Query4CondRangeDropCacheTotal(State& state); + void Query4CondRangeDropCacheCachedTotal(State& state); void query2CondIdSet(State& state, const std::vector>& idsets); reindexer::Error prepareCJsonBench(); @@ -90,6 +130,7 @@ class ApiTvSimple : private BaseFixture { std::vector countries_; std::vector countryLikePatterns_; std::vector locations_; + std::vector devices_; std::vector start_times_; std::vector> packages_; std::vector> priceIDs_; diff --git a/cpp_src/gtests/bench/fixtures/api_tv_simple_comparators.cc b/cpp_src/gtests/bench/fixtures/api_tv_simple_comparators.cc index 48a1306f0..30846061c 100644 --- a/cpp_src/gtests/bench/fixtures/api_tv_simple_comparators.cc +++ b/cpp_src/gtests/bench/fixtures/api_tv_simple_comparators.cc @@ -454,7 +454,7 @@ void ApiTvSimpleComparators::Query4CondCachedTotal(benchmark::State& state) { void ApiTvSimpleComparators::Query4CondRange(benchmark::State& state) { AllocsTracker allocsTracker(state); for (auto _ : state) { // NOLINT(*deadcode.DeadStores) - int startTime = random(0, 50000); + int startTime = random(0, 30000); int endTime = startTime + 10000; Query q(nsdef_.name); q.Limit(20) @@ -473,7 +473,7 @@ void ApiTvSimpleComparators::Query4CondRange(benchmark::State& state) { void ApiTvSimpleComparators::Query4CondRangeTotal(benchmark::State& state) { AllocsTracker allocsTracker(state); for (auto _ : state) { // NOLINT(*deadcode.DeadStores) - int startTime = random(0, 50000); + int startTime = random(0, 30000); int endTime = startTime + 10000; Query q(nsdef_.name); q.Limit(20) @@ -493,7 +493,7 @@ void ApiTvSimpleComparators::Query4CondRangeTotal(benchmark::State& state) { void ApiTvSimpleComparators::Query4CondRangeCachedTotal(benchmark::State& state) { AllocsTracker allocsTracker(state); for (auto _ : state) { // NOLINT(*deadcode.DeadStores) - int startTime = random(0, 50000); + int startTime = random(0, 30000); int endTime = startTime + 10000; Query q(nsdef_.name); q.Limit(20) diff --git a/cpp_src/gtests/bench/fixtures/ft_fixture.cc b/cpp_src/gtests/bench/fixtures/ft_fixture.cc index 955ee9d66..f7358ae57 100644 --- a/cpp_src/gtests/bench/fixtures/ft_fixture.cc +++ b/cpp_src/gtests/bench/fixtures/ft_fixture.cc @@ -112,51 +112,50 @@ reindexer::Error FullText::Initialize() { return {}; } -void FullText::RegisterAllCases(size_t iterationCount) { +void FullText::RegisterAllCases(std::optional fastIterationCount, std::optional slowIterationCount) { constexpr static auto Mem = reindexer::FtFastConfig::Optimization::Memory; constexpr static auto CPU = reindexer::FtFastConfig::Optimization::CPU; - RegisterWrapper wrap(iterationCount); //-1 test limit - default time + RegisterWrapper wrapSlow(slowIterationCount); // std::numeric_limits::max() test limit - default time + RegisterWrapper wrapFast(fastIterationCount); // NOLINTBEGIN(*cplusplus.NewDeleteLeaks) Register("BuildAndInsertNs2", &FullText::BuildAndInsertLowWordsDiversityNs, this)->Iterations(1000)->Unit(benchmark::kMicrosecond); - wrap.SetOptions(Register("Fast3PhraseLowDiversity", &FullText::Fast3PhraseLowDiversity, this)); - wrap.SetOptions(Register("Fast3WordsLowDiversity", &FullText::Fast3WordsLowDiversity, this)); + wrapSlow.SetOptions(Register("Fast3PhraseLowDiversity", &FullText::Fast3PhraseLowDiversity, this)); + wrapSlow.SetOptions(Register("Fast3WordsLowDiversity", &FullText::Fast3WordsLowDiversity, this)); - wrap.SetOptions(Register("Fast3WordsWithAreasLowDiversity", &FullText::Fast3WordsWithAreasLowDiversity, this)); - wrap.SetOptions(Register("Fast3PhraseWithAreasLowDiversity", &FullText::Fast3PhraseWithAreasLowDiversity, this)); + wrapSlow.SetOptions(Register("Fast3WordsWithAreasLowDiversity", &FullText::Fast3WordsWithAreasLowDiversity, this)); + wrapSlow.SetOptions(Register("Fast3PhraseWithAreasLowDiversity", &FullText::Fast3PhraseWithAreasLowDiversity, this)); - wrap.SetOptions(Register("Fast2PhraseLowDiversity", &FullText::Fast2PhraseLowDiversity, this)); - wrap.SetOptions(Register("Fast2AndWordLowDiversity", &FullText::Fast2AndWordLowDiversity, this)); + wrapFast.SetOptions(Register("Fast2PhraseLowDiversity", &FullText::Fast2PhraseLowDiversity, this)); + wrapFast.SetOptions(Register("Fast2AndWordLowDiversity", &FullText::Fast2AndWordLowDiversity, this)); Register("Insert", &FullText::Insert, this)->Iterations(id_seq_->Count())->Unit(benchmark::kMicrosecond); - // Register("BuildCommonIndexes", &FullText::BuildCommonIndexes, this)->Iterations(1)->Unit(benchmark::kMicrosecond); Register("BuildFastTextIndex", &FullText::BuildFastTextIndex, this)->Iterations(1)->Unit(benchmark::kMicrosecond); - // Register("BuildFuzzyTextIndex", &FullText::BuildFuzzyTextIndex, this)->Iterations(1)->Unit(benchmark::kMicrosecond); - - wrap.SetOptions(Register("Fast1WordMatch.OptByMem", &FullText::Fast1WordMatch, this)); - wrap.SetOptions(Register("Fast2WordsMatch.OptByMem", &FullText::Fast2WordsMatch, this)); - wrap.SetOptions(Register("Fast1PrefixMatch.OptByMem", &FullText::Fast1PrefixMatch, this)); - wrap.SetOptions(Register("Fast2PrefixMatch.OptByMem", &FullText::Fast2PrefixMatch, this)); - wrap.SetOptions(Register("Fast1SuffixMatch.OptByMem", &FullText::Fast1SuffixMatch, this)); - wrap.SetOptions(Register("Fast2SuffixMatch.OptByMem", &FullText::Fast2SuffixMatch, this)); - - wrap.SetOptions(Register("Fast1TypoWordMatch.OptByMem", &FullText::Fast1TypoWordMatch, this)); - wrap.SetOptions(Register("Fast2TypoWordMatch.OptByMem", &FullText::Fast2TypoWordMatch, this)); - wrap.SetOptions(Register("Fast1WordWithAreaHighDiversity.optByMem", &FullText::Fast1WordWithAreaHighDiversity, this)); + wrapFast.SetOptions(Register("Fast1WordMatch.OptByMem", &FullText::Fast1WordMatch, this)); + wrapFast.SetOptions(Register("Fast2WordsMatch.OptByMem", &FullText::Fast2WordsMatch, this)); + wrapSlow.SetOptions(Register("Fast1PrefixMatch.OptByMem", &FullText::Fast1PrefixMatch, this)); + wrapSlow.SetOptions(Register("Fast2PrefixMatch.OptByMem", &FullText::Fast2PrefixMatch, this)); + wrapSlow.SetOptions(Register("Fast1SuffixMatch.OptByMem", &FullText::Fast1SuffixMatch, this)); + wrapSlow.SetOptions(Register("Fast2SuffixMatch.OptByMem", &FullText::Fast2SuffixMatch, this)); + wrapFast.SetOptions(Register("Fast1TypoWordMatch.OptByMem", &FullText::Fast1TypoWordMatch, this)); + wrapFast.SetOptions(Register("Fast2TypoWordMatch.OptByMem", &FullText::Fast2TypoWordMatch, this)); + wrapFast.SetOptions(Register("Fast1WordWithAreaHighDiversity.OptByMem", &FullText::Fast1WordWithAreaHighDiversity, this)); Register("SetOptimizationByCPU", &FullText::UpdateIndex, this)->Iterations(1)->Unit(benchmark::kMicrosecond); - wrap.SetOptions(Register("Fast1WordMatch.OptByCPU", &FullText::Fast1WordMatch, this)); + wrapFast.SetOptions(Register("Fast1WordMatch.OptByCPU", &FullText::Fast1WordMatch, this)); + wrapFast.SetOptions(Register("Fast2WordsMatch.OptByCPU", &FullText::Fast2WordsMatch, this)); + wrapSlow.SetOptions(Register("Fast1PrefixMatch.OptByCPU", &FullText::Fast1PrefixMatch, this)); + wrapSlow.SetOptions(Register("Fast2PrefixMatch.OptByCPU", &FullText::Fast2PrefixMatch, this)); + wrapSlow.SetOptions(Register("Fast1SuffixMatch.OptByCPU", &FullText::Fast1SuffixMatch, this)); + wrapSlow.SetOptions(Register("Fast2SuffixMatch.OptByCPU", &FullText::Fast2SuffixMatch, this)); + wrapFast.SetOptions(Register("Fast1TypoWordMatch.OptByCPU", &FullText::Fast1TypoWordMatch, this)); + wrapFast.SetOptions(Register("Fast2TypoWordMatch.OptByCPU", &FullText::Fast2TypoWordMatch, this)); + wrapFast.SetOptions(Register("Fast1WordWithAreaHighDiversity.OptByCPU", &FullText::Fast1WordWithAreaHighDiversity, this)); - wrap.SetOptions(Register("Fast2WordsMatch.OptByCPU", &FullText::Fast2WordsMatch, this)); - wrap.SetOptions(Register("Fast1PrefixMatch.OptByCPU", &FullText::Fast1PrefixMatch, this)); - wrap.SetOptions(Register("Fast2PrefixMatch.OptByCPU", &FullText::Fast2PrefixMatch, this)); - wrap.SetOptions(Register("Fast1SuffixMatch.OptByCPU", &FullText::Fast1SuffixMatch, this)); - wrap.SetOptions(Register("Fast2SuffixMatch.OptByCPU", &FullText::Fast2SuffixMatch, this)); - wrap.SetOptions(Register("Fast1TypoWordMatch.OptByCPU", &FullText::Fast1TypoWordMatch, this)); - wrap.SetOptions(Register("Fast2TypoWordMatch.OptByCPU", &FullText::Fast2TypoWordMatch, this)); + // Register("BuildFuzzyTextIndex", &FullText::BuildFuzzyTextIndex, this)->Iterations(1)->Unit(benchmark::kMicrosecond); // Register("Fuzzy1WordMatch", &FullText::Fuzzy1WordMatch, this)->Unit(benchmark::kMicrosecond); // Register("Fuzzy2WordsMatch", &FullText::Fuzzy2WordsMatch, this)->Unit(benchmark::kMicrosecond); @@ -198,17 +197,19 @@ void FullText::RegisterAllCases(size_t iterationCount) { Register("InitForAlternatingUpdatesAndSelects.OptByMem", &FullText::InitForAlternatingUpdatesAndSelects, this) ->Iterations(1) ->Unit(benchmark::kMicrosecond); - wrap.SetOptions(Register("AlternatingUpdatesAndSelects.OptByMem", &FullText::AlternatingUpdatesAndSelects, this)); - wrap.SetOptions(Register("AlternatingUpdatesAndSelectsByComposite.OptByMem", &FullText::AlternatingUpdatesAndSelectsByComposite, this)); - wrap.SetOptions(Register("AlternatingUpdatesAndSelectsByCompositeByNotIndexFields.OptByMem", - &FullText::AlternatingUpdatesAndSelectsByCompositeByNotIndexFields, this)); + wrapFast.SetOptions(Register("AlternatingUpdatesAndSelects.OptByMem", &FullText::AlternatingUpdatesAndSelects, this)); + wrapFast.SetOptions( + Register("AlternatingUpdatesAndSelectsByComposite.OptByMem", &FullText::AlternatingUpdatesAndSelectsByComposite, this)); + wrapFast.SetOptions(Register("AlternatingUpdatesAndSelectsByCompositeByNotIndexFields.OptByMem", + &FullText::AlternatingUpdatesAndSelectsByCompositeByNotIndexFields, this)); Register("InitForAlternatingUpdatesAndSelects.OptByCPU", &FullText::InitForAlternatingUpdatesAndSelects, this) ->Iterations(1) ->Unit(benchmark::kMicrosecond); - wrap.SetOptions(Register("AlternatingUpdatesAndSelects.OptByCPU", &FullText::AlternatingUpdatesAndSelects, this)); - wrap.SetOptions(Register("AlternatingUpdatesAndSelectsByComposite.OptByCPU", &FullText::AlternatingUpdatesAndSelectsByComposite, this)); - wrap.SetOptions(Register("AlternatingUpdatesAndSelectsByCompositeByNotIndexFields.OptByCPU", - &FullText::AlternatingUpdatesAndSelectsByCompositeByNotIndexFields, this)); + wrapFast.SetOptions(Register("AlternatingUpdatesAndSelects.OptByCPU", &FullText::AlternatingUpdatesAndSelects, this)); + wrapFast.SetOptions( + Register("AlternatingUpdatesAndSelectsByComposite.OptByCPU", &FullText::AlternatingUpdatesAndSelectsByComposite, this)); + wrapFast.SetOptions(Register("AlternatingUpdatesAndSelectsByCompositeByNotIndexFields.OptByCPU", + &FullText::AlternatingUpdatesAndSelectsByCompositeByNotIndexFields, this)); // NOLINTEND(*cplusplus.NewDeleteLeaks) } @@ -985,25 +986,26 @@ void FullText::InitForAlternatingUpdatesAndSelects(State& state) { // Init index build assert(!values_.empty()); - Query q = + const Query q1 = Query(alternatingNs_) .Where("search1", CondEq, values_[randomGenerator_(randomEngine_, std::uniform_int_distribution::param_type{0, int(values_.size() - 1)})] .search1); QueryResults qres; - err = db_->Select(q, qres); + err = db_->Select(q1, qres); if (!err.ok()) state.SkipWithError(err.what().c_str()); size_t index = randomGenerator_(randomEngine_, std::uniform_int_distribution::param_type{0, int(values_.size() - 1)}); - q = Query(alternatingNs_).Where("search_comp", CondEq, values_[index].search1 + ' ' + values_[index].search2); + const Query q2 = Query(alternatingNs_).Where("search_comp", CondEq, values_[index].search1 + ' ' + values_[index].search2); qres.Clear(); - err = db_->Select(q, qres); + err = db_->Select(q2, qres); if (!err.ok()) state.SkipWithError(err.what().c_str()); index = randomGenerator_(randomEngine_, std::uniform_int_distribution::param_type{0, int(values_.size() - 1)}); - q = Query(alternatingNs_).Where("search_comp_not_index_fields", CondEq, values_[index].field1 + ' ' + values_[index].field2); + const Query q3 = + Query(alternatingNs_).Where("search_comp_not_index_fields", CondEq, values_[index].field1 + ' ' + values_[index].field2); qres.Clear(); - err = db_->Select(q, qres); + err = db_->Select(q3, qres); if (!err.ok()) state.SkipWithError(err.what().c_str()); } diff --git a/cpp_src/gtests/bench/fixtures/ft_fixture.h b/cpp_src/gtests/bench/fixtures/ft_fixture.h index 13f69eb43..954e89c7e 100644 --- a/cpp_src/gtests/bench/fixtures/ft_fixture.h +++ b/cpp_src/gtests/bench/fixtures/ft_fixture.h @@ -19,7 +19,7 @@ class FullText : private BaseFixture { FullText(Reindexer* db, const std::string& name, size_t maxItems); virtual reindexer::Error Initialize() override; - void RegisterAllCases(size_t iterationCount = -1); + void RegisterAllCases(std::optional fastIterationCount, std::optional slowIterationCount); private: virtual reindexer::Item MakeItem(benchmark::State&) override; @@ -101,18 +101,16 @@ class FullText : private BaseFixture { class RegisterWrapper { public: - //-1 test iteration limit - time - RegisterWrapper(size_t iterationCoun = -1) : iterationCoun_(iterationCoun) {} - Benchmark* SetOptions(Benchmark* b) { - b = b->Unit(benchmark::kMicrosecond); - if (iterationCoun_ != size_t(-1)) { - b = b->Iterations(iterationCoun_); + RegisterWrapper(std::optional iterationCoun) noexcept : iterationCoun_(iterationCoun) {} + void SetOptions(Benchmark* b) { + if (iterationCoun_.has_value()) { + b = b->Iterations(*iterationCoun_); } - return b; + b->Unit(benchmark::kMicrosecond); } private: - size_t iterationCoun_; + std::optional iterationCoun_; }; #ifdef ENABLE_TIME_TRACKER #define TIMETRACKER(fileName) TimeTracker timeTracker(fileName); diff --git a/cpp_src/gtests/bench/ft_bench.cc b/cpp_src/gtests/bench/ft_bench.cc index 05b81d1de..02a9ff7f7 100644 --- a/cpp_src/gtests/bench/ft_bench.cc +++ b/cpp_src/gtests/bench/ft_bench.cc @@ -39,22 +39,30 @@ int main(int argc, char** argv) { if (!err.ok()) return err.code(); ::benchmark::Initialize(&argc, argv); - size_t iterationCount = -1; // count is determined by the execution time + std::optional slowIterationCount; + std::optional fastIterationCount; if (argc > 1) { try { args::ArgumentParser parser("ft_bench additional args"); - args::ValueFlag iterCountF(parser, "ITERCOUNT", "iteration count", {"iteration_count"}, args::Options::Single); + args::ValueFlag siterCountF(parser, "SITERCOUNT", "iteration count for the slow cases", {"slow_iteration_count"}, + args::Options::Single); + args::ValueFlag fiterCountF(parser, "FITERCOUNT", "iteration count for the fast cases", {"fast_iteration_count"}, + args::Options::Single); parser.ParseCLI(argc, argv); - if (iterCountF) { - iterationCount = args::get(iterCountF); - argc--; // only one additional argument, otherwise need to rearrange the argv rows + if (siterCountF) { + slowIterationCount = args::get(siterCountF); + argc--; // sub argument, otherwise need to rearrange the argv rows + } + if (fiterCountF) { + fastIterationCount = args::get(fiterCountF); + argc--; // sub additional argument, otherwise need to rearrange the argv rows } } catch (const args::ParseError& e) { std::cout << "argument parse error '" << e.what() << "'" << std::endl; return 1; } } - ft.RegisterAllCases(iterationCount); + ft.RegisterAllCases(fastIterationCount, slowIterationCount); #ifdef _GLIBCXX_DEBUG ::benchmark::RunSpecifiedBenchmarks(); diff --git a/cpp_src/gtests/tests/API/api.cc b/cpp_src/gtests/tests/API/api.cc index bdb97049f..cf14719c5 100644 --- a/cpp_src/gtests/tests/API/api.cc +++ b/cpp_src/gtests/tests/API/api.cc @@ -1,9 +1,19 @@ #include #include "gtest/gtest.h" +#include "tools/assertrx.h" +#include "tools/fsops.h" -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { srand(time(NULL)); ::testing::InitGoogleTest(&argc, argv); + +#ifndef _WIN32 + const char *tmpDir = getenv("REINDEXER_TEST_DB_ROOT"); + if (tmpDir && *tmpDir) { + reindexer::fs::SetTempDir(std::string(tmpDir)); + } +#endif // _WIN32 + return RUN_ALL_TESTS(); } diff --git a/cpp_src/gtests/tests/API/base_tests.cc b/cpp_src/gtests/tests/API/base_tests.cc index 1f1751cd0..491319105 100644 --- a/cpp_src/gtests/tests/API/base_tests.cc +++ b/cpp_src/gtests/tests/API/base_tests.cc @@ -21,8 +21,6 @@ #include "server/loggerwrapper.h" #include "tools/serializer.h" -static const std::string kBaseTestsStoragePath = "/tmp/reindex/base_tests"; - TEST_F(ReindexerApi, AddNamespace) { auto err = rt.reindexer->OpenNamespace(default_namespace, StorageOpts().Enabled(false)); ASSERT_EQ(true, err.ok()) << err.what(); @@ -507,6 +505,7 @@ TEST_F(ReindexerApi, CloseNamespace) { } TEST_F(ReindexerApi, DropStorage) { + const std::string kBaseTestsStoragePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex/api_drop_storage/"); auto rx = std::make_unique(); auto err = rx->Connect("builtin://" + kBaseTestsStoragePath); ASSERT_TRUE(err.ok()) << err.what(); @@ -1321,9 +1320,8 @@ TEST_F(ReindexerApi, DslFieldsTest) { TEST_F(ReindexerApi, DistinctQueriesEncodingTest) { const std::string sql = "select distinct(country), distinct(city) from clients;"; - Query q1; - q1.FromSQL(sql); - EXPECT_EQ(q1.entries.Size(), 0); + Query q1 = Query::FromSQL(sql); + EXPECT_EQ(q1.Entries().Size(), 0); ASSERT_EQ(q1.aggregations_.size(), 2); EXPECT_EQ(q1.aggregations_[0].Type(), AggDistinct); ASSERT_EQ(q1.aggregations_[0].Fields().size(), 1); @@ -1334,14 +1332,14 @@ TEST_F(ReindexerApi, DistinctQueriesEncodingTest) { std::string dsl = q1.GetJSON(); Query q2; - q2.FromJSON(dsl); + const auto err = q2.FromJSON(dsl); + ASSERT_TRUE(err.ok()) << err.what(); EXPECT_EQ(q1, q2) << "q1: " << q1.GetSQL() << "\nq2: " << q2.GetSQL(); Query q3{Query(default_namespace).Distinct("name").Distinct("city").Where("id", CondGt, static_cast(10))}; std::string sql2 = q3.GetSQL(); - Query q4; - q4.FromSQL(sql2); + Query q4 = Query::FromSQL(sql2); EXPECT_EQ(q3, q4) << "q3: " << q3.GetSQL() << "\nq4: " << q4.GetSQL(); EXPECT_EQ(sql2, q4.GetSQL()); } @@ -1443,21 +1441,19 @@ TEST_F(ReindexerApi, ContextCancelingTest) { } TEST_F(ReindexerApi, JoinConditionsSqlParserTest) { - Query q1, q2; const std::string sql1 = "SELECT * FROM ns WHERE a > 0 AND INNER JOIN (SELECT * FROM ns2 WHERE b > 10 AND c = 1) ON ns2.id = ns.fk_id"; - q1.FromSQL(sql1); + const auto q1 = Query::FromSQL(sql1); ASSERT_EQ(q1.GetSQL(), sql1); const std::string sql2 = "SELECT * FROM ns WHERE a > 0 AND INNER JOIN (SELECT * FROM ns2 WHERE b > 10 AND c = 1 LIMIT 0) ON ns2.id = ns.fk_id"; - q2.FromSQL(sql2); + const auto q2 = Query::FromSQL(sql2); ASSERT_EQ(q2.GetSQL(), sql2); } TEST_F(ReindexerApi, UpdateWithBoolParserTest) { - Query query; const std::string sql = "UPDATE ns SET flag1 = true,flag2 = false WHERE id > 100"; - query.FromSQL(sql); + Query query = Query::FromSQL(sql); ASSERT_EQ(query.UpdateFields().size(), 2); EXPECT_EQ(query.UpdateFields().front().Column(), "flag1"); EXPECT_EQ(query.UpdateFields().front().Mode(), FieldModeSet); @@ -1477,14 +1473,13 @@ TEST_F(ReindexerApi, EqualPositionsSqlParserTest) { "SELECT * FROM ns WHERE (f1 = 1 AND f2 = 2 OR f3 = 3 equal_position(f1, f2) equal_position(f1, f3)) OR (f4 = 4 AND f5 > 5 " "equal_position(f4, f5))"; - Query query; - query.FromSQL(sql); + Query query = Query::FromSQL(sql); EXPECT_EQ(query.GetSQL(), sql); - EXPECT_TRUE(query.entries.equalPositions.empty()); - ASSERT_EQ(query.entries.Size(), 7); + EXPECT_TRUE(query.Entries().equalPositions.empty()); + ASSERT_EQ(query.Entries().Size(), 7); - ASSERT_TRUE(query.entries.IsSubTree(0)); - const auto& ep1 = query.entries.Get(0).equalPositions; + ASSERT_TRUE(query.Entries().IsSubTree(0)); + const auto& ep1 = query.Entries().Get(0).equalPositions; ASSERT_EQ(ep1.size(), 2); ASSERT_EQ(ep1[0].size(), 2); EXPECT_EQ(ep1[0][0], "f1"); @@ -1493,8 +1488,8 @@ TEST_F(ReindexerApi, EqualPositionsSqlParserTest) { EXPECT_EQ(ep1[1][0], "f1"); EXPECT_EQ(ep1[1][1], "f3"); - ASSERT_TRUE(query.entries.IsSubTree(4)); - const auto& ep2 = query.entries.Get(4).equalPositions; + ASSERT_TRUE(query.Entries().IsSubTree(4)); + const auto& ep2 = query.Entries().Get(4).equalPositions; ASSERT_EQ(ep2.size(), 1); ASSERT_EQ(ep2[0].size(), 2); EXPECT_EQ(ep2[0][0], "f4"); @@ -1552,48 +1547,20 @@ TEST_F(ReindexerApi, SchemaSuggestions) { err = rt.reindexer->SetSchema(default_namespace, jsonschema); ASSERT_TRUE(err.ok()) << err.what(); - auto validateSuggestions = [](const std::vector& actual, const std::unordered_set& expected) { - ASSERT_EQ(actual.size(), expected.size()); - for (auto& sugg : actual) { + auto validateSuggestions = [this](std::string_view sql, const std::unordered_set& expected) { + std::vector suggestions; + auto err = rt.reindexer->GetSqlSuggestions(sql, sql.size() - 1, suggestions); + ASSERT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(suggestions.size(), expected.size()) << sql; + for (auto& sugg : suggestions) { EXPECT_TRUE(expected.find(sugg) != expected.end()) << "Unexpected suggestion: " << sugg; } }; - { - std::unordered_set expected = {"Nest_fake", "nested"}; - std::vector suggestions; - std::string_view query = "select * from test_namespace where ne"; - err = rt.reindexer->GetSqlSuggestions(query, query.size() - 1, suggestions); - ASSERT_TRUE(err.ok()) << err.what(); - validateSuggestions(suggestions, expected); - } - - { - std::unordered_set expected; - std::vector suggestions; - std::string_view query = "select * from test_namespace where nested"; - err = rt.reindexer->GetSqlSuggestions(query, query.size() - 1, suggestions); - ASSERT_TRUE(err.ok()) << err.what(); - validateSuggestions(suggestions, expected); - } - - { - std::unordered_set expected = {".Name", ".Naame", ".Age"}; - std::vector suggestions; - std::string_view query = "select * from test_namespace where nested."; - err = rt.reindexer->GetSqlSuggestions(query, query.size() - 1, suggestions); - ASSERT_TRUE(err.ok()) << err.what(); - validateSuggestions(suggestions, expected); - } - - { - std::unordered_set expected = {".Name", ".Naame"}; - std::vector suggestions; - std::string_view query = "select * from test_namespace where nested.Na"; - err = rt.reindexer->GetSqlSuggestions(query, query.size() - 1, suggestions); - ASSERT_TRUE(err.ok()) << err.what(); - validateSuggestions(suggestions, expected); - } + validateSuggestions("select * from test_namespace where ne", {"Nest_fake", "nested"}); + validateSuggestions("select * from test_namespace where nested", {}); + validateSuggestions("select * from test_namespace where nested.", {".Name", ".Naame", ".Age"}); + validateSuggestions("select * from test_namespace where nested.Na", {".Name", ".Naame"}); } TEST_F(ReindexerApi, LoggerWriteInterruptTest) { @@ -1613,7 +1580,7 @@ TEST_F(ReindexerApi, LoggerWriteInterruptTest) { spdlog::drop_all(); std::remove(logFile.c_str()); } - const std::string logFile = "/tmp/logtest.out"; + const std::string logFile = "/tmp/reindex_logtest.out"; reindexer_server::LoggerWrapper logger; std::shared_ptr sinkPtr; } instance; @@ -1686,18 +1653,16 @@ TEST_F(ReindexerApi, SelectFilterWithAggregationConstraints) { Query q; std::string sql = "select id, distinct(year) from test_namespace"; - EXPECT_NO_THROW(q.FromSQL(sql)); + EXPECT_NO_THROW(q = Query::FromSQL(sql)); Error status = Query().FromJSON(q.GetJSON()); EXPECT_TRUE(status.ok()) << status.what(); - q = Query(); - q.selectFilter_.emplace_back("id"); + q = Query().Select({"id"}); EXPECT_NO_THROW(q.Aggregate(AggDistinct, {"year"}, {})); sql = "select id, max(year) from test_namespace"; - EXPECT_THROW(q.FromSQL(sql), Error); - q = Query(default_namespace); - q.selectFilter_.emplace_back("id"); + EXPECT_THROW(q = Query::FromSQL(sql), Error); + q = Query(default_namespace).Select({"id"}); q.aggregations_.emplace_back(reindexer::AggregateEntry{AggMax, {"year"}}); status = Query().FromJSON(q.GetJSON()); EXPECT_FALSE(status.ok()); @@ -1705,23 +1670,39 @@ TEST_F(ReindexerApi, SelectFilterWithAggregationConstraints) { EXPECT_THROW(q.Aggregate(AggMax, {"price"}, {}), Error); sql = "select facet(year), id, name from test_namespace"; - EXPECT_THROW(q.FromSQL(sql), Error); - q = Query(default_namespace); - q.selectFilter_.emplace_back("id"); - q.selectFilter_.emplace_back("name"); + EXPECT_THROW(q = Query::FromSQL(sql), Error); + q = Query(default_namespace).Select({"id", "name"}); EXPECT_THROW(q.Aggregate(AggFacet, {"year"}, {}), Error); - q = Query(default_namespace); - EXPECT_NO_THROW(q.Aggregate(AggFacet, {"year"}, {})); - q.selectFilter_.emplace_back("id"); - q.selectFilter_.emplace_back("name"); - status = Query().FromJSON(q.GetJSON()); + status = Query().FromJSON(fmt::sprintf(R"({"namespace":"%s", + "limit":-1, + "offset":0, + "req_total":"disabled", + "explain":false, + "type":"select", + "select_with_rank":false, + "select_filter":[ + "id", + "name" + ], + "select_functions":[], + "sort":[], + "filters":[], + "merge_queries":[], + "aggregations":[ + { + "type":"facet", + "sort":[], + "fields":["year"] + } + ]})", + default_namespace)); EXPECT_FALSE(status.ok()); EXPECT_TRUE(status.what() == std::string(reindexer::kAggregationWithSelectFieldsMsgError)); - EXPECT_THROW(Query().FromSQL("select max(id), * from test_namespace"), Error); - EXPECT_THROW(Query().FromSQL("select *, max(id) from test_namespace"), Error); - EXPECT_NO_THROW(Query().FromSQL("select *, count(*) from test_namespace")); - EXPECT_NO_THROW(Query().FromSQL("select count(*), * from test_namespace")); + EXPECT_THROW((void)Query::FromSQL("select max(id), * from test_namespace"), Error); + EXPECT_THROW((void)Query::FromSQL("select *, max(id) from test_namespace"), Error); + EXPECT_NO_THROW((void)Query::FromSQL("select *, count(*) from test_namespace")); + EXPECT_NO_THROW((void)Query::FromSQL("select count(*), * from test_namespace")); } TEST_F(ReindexerApi, InsertIncorrectItemWithJsonPathsDuplication) { @@ -1840,11 +1821,11 @@ TEST_F(ReindexerApi, UpdateDoublesItemByPKIndex) { { reindexer::QueryResults qr; - Query query; const std::string sql = "UPDATE test_namespace SET v1=125, id = 3 WHERE id = 2"; - query.FromSQL(sql); + Query query = Query::FromSQL(sql); err = rt.reindexer->Update(query, qr); - ASSERT_FALSE(err.ok()); + ASSERT_EQ(err.code(), errLogic); + EXPECT_EQ(err.what(), "Duplicate Primary Key {id: {3}} for rows [2, 3]!"); } { diff --git a/cpp_src/gtests/tests/fixtures/clientsstats_api.h b/cpp_src/gtests/tests/fixtures/clientsstats_api.h index 7df859ab9..87e70d4dd 100644 --- a/cpp_src/gtests/tests/fixtures/clientsstats_api.h +++ b/cpp_src/gtests/tests/fixtures/clientsstats_api.h @@ -25,7 +25,7 @@ class ClientsStatsApi : public ::testing::Test { void SetProfilingFlag(bool val, const std::string& column, reindexer::client::CoroReindexer& c); - const std::string kdbPath = "/tmp/testdb/"; + const std::string kdbPath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "clientstats_test"); const std::string kdbName = "test"; const std::string kipaddress = "127.0.0.1"; const uint16_t kPortI = 7777; diff --git a/cpp_src/gtests/tests/fixtures/ft_api.cc b/cpp_src/gtests/tests/fixtures/ft_api.cc index 9f5c9ac81..08e93be72 100644 --- a/cpp_src/gtests/tests/fixtures/ft_api.cc +++ b/cpp_src/gtests/tests/fixtures/ft_api.cc @@ -190,7 +190,7 @@ reindexer::QueryResults FTApi::SimpleCompositeSelect(std::string word) { auto mqr{reindexer::Query("nm2").Where("ft3", CondEq, std::move(word))}; mqr.AddFunction("ft1 = snippet(,\"\",3,2,,d)"); - qr.mergeQueries_.emplace_back(Merge, std::move(mqr)); + qr.Merge(std::move(mqr)); qr.AddFunction("ft3 = highlight(,)"); auto err = rt.reindexer->Select(qr, res); EXPECT_TRUE(err.ok()) << err.what(); @@ -205,7 +205,7 @@ reindexer::QueryResults FTApi::CompositeSelectField(const std::string& field, st auto mqr{reindexer::Query("nm2").Where("ft3", CondEq, std::move(word))}; mqr.AddFunction(field + " = snippet(,\"\",3,2,,d)"); - qr.mergeQueries_.emplace_back(Merge, std::move(mqr)); + qr.Merge(std::move(mqr)); qr.AddFunction(field + " = highlight(,)"); auto err = rt.reindexer->Select(qr, res); EXPECT_TRUE(err.ok()) << err.what(); diff --git a/cpp_src/gtests/tests/fixtures/fuzzing/index.cc b/cpp_src/gtests/tests/fixtures/fuzzing/index.cc index cb9f50d4e..17f7f9c59 100644 --- a/cpp_src/gtests/tests/fixtures/fuzzing/index.cc +++ b/cpp_src/gtests/tests/fixtures/fuzzing/index.cc @@ -13,7 +13,7 @@ reindexer::IndexDef Index::IndexDef(RandomGenerator& rnd, const NsScheme& scheme IndexOpts opts; const bool pk = rnd.PkIndex(isPk_); opts.PK(pk); - opts.Array(rnd.RndArrayField(isArray_) == IsArray::Yes); + opts.Array(rnd.RndArrayField(isArray_) == IsArrayT::Yes); opts.Sparse(rnd.RndSparseIndex(isSparse_)); opts.Dense(rnd.DenseIndex()); opts.RTreeType(static_cast(rnd.RndInt(IndexOpts::Linear, IndexOpts::RStar))); @@ -58,7 +58,7 @@ void Index::Dump(std::ostream& os, const NsScheme& scheme, size_t offset) const for (size_t i = 0; i <= offset; ++i) os << " "; os << "array: " << std::boolalpha << IsArray() << '\n'; for (size_t i = 0; i <= offset; ++i) os << " "; - os << "sparse: " << std::boolalpha << (IsSparse() == IsSparse::Yes) << '\n'; + os << "sparse: " << std::boolalpha << (IsSparse() == IsSparseT::Yes) << '\n'; for (size_t i = 0; i <= offset; ++i) os << " "; std::visit(reindexer::overloaded{[&](const Child& child) { os << "composite: false\n"; diff --git a/cpp_src/gtests/tests/fixtures/fuzzing/index.h b/cpp_src/gtests/tests/fixtures/fuzzing/index.h index 80407211c..4fe90a47b 100644 --- a/cpp_src/gtests/tests/fixtures/fuzzing/index.h +++ b/cpp_src/gtests/tests/fixtures/fuzzing/index.h @@ -22,9 +22,9 @@ class Index { }; using Children = std::vector; - Index(std::string name, IndexType type, IsArray isArray, IsSparse isSparse, Children content) noexcept + Index(std::string name, IndexType type, IsArrayT isArray, IsSparseT isSparse, Children content) noexcept : name_{std::move(name)}, type_{type}, content_{std::move(content)}, isArray_{isArray}, isSparse_{isSparse} {} - Index(std::string name, IndexType type, IsArray isArray, IsSparse isSparse, Child content) noexcept + Index(std::string name, IndexType type, IsArrayT isArray, IsSparseT isSparse, Child content) noexcept : name_{std::move(name)}, type_{type}, content_{std::move(content)}, isArray_{isArray}, isSparse_{isSparse} {} const std::string& Name() const& noexcept { return name_; } @@ -34,7 +34,7 @@ class Index { const auto& Content() const&& = delete; bool IsPk() const noexcept { return isPk_; } void SetPk() noexcept { isPk_ = true; } - bool IsArray() const noexcept { return isArray_ == IsArray::Yes; } + bool IsArray() const noexcept { return isArray_ == IsArrayT::Yes; } auto IsSparse() const noexcept { return isSparse_; } reindexer::IndexDef IndexDef(RandomGenerator&, const NsScheme&, const std::vector&) const; @@ -46,8 +46,8 @@ class Index { IndexType type_; std::variant content_; bool isPk_{false}; - enum IsArray isArray_ { IsArray::No }; - enum IsSparse isSparse_ { IsSparse::No }; + IsArrayT isArray_{IsArrayT::No}; + IsSparseT isSparse_{IsSparseT::No}; }; } // namespace fuzzing diff --git a/cpp_src/gtests/tests/fixtures/fuzzing/ns.cc b/cpp_src/gtests/tests/fixtures/fuzzing/ns.cc index 5a520d4a0..831653a84 100644 --- a/cpp_src/gtests/tests/fixtures/fuzzing/ns.cc +++ b/cpp_src/gtests/tests/fixtures/fuzzing/ns.cc @@ -99,7 +99,7 @@ Ns::Ns(std::string name, RandomGenerator::ErrFactorType errorFactor) usedIndexNames.insert(name); } - indexes_.emplace_back(std::move(name), indexType, rndGen_.RndArrayField(array ? IsArray::Yes : IsArray::No), IsSparse::No, + indexes_.emplace_back(std::move(name), indexType, rndGen_.RndArrayField(array ? IsArrayT::Yes : IsArrayT::No), IsSparseT::No, std::move(children)); } else { FieldPath fldPath; @@ -113,8 +113,8 @@ Ns::Ns(std::string name, RandomGenerator::ErrFactorType errorFactor) if (!rndGen_.RndErr()) continue; const auto fldType = rndGen_.RndFieldType(); indexes_.emplace_back(rndGen_.IndexName(usedIndexNames), rndGen_.RndIndexType({fldType}), - rndGen_.RndBool(0.5) ? IsArray::Yes : IsArray::No, - rndGen_.RndBool(0.5) ? IsSparse::Yes : IsSparse::No, Index::Child{fldType, std::move(fldPath)}); + rndGen_.RndBool(0.5) ? IsArrayT::Yes : IsArrayT::No, + rndGen_.RndBool(0.5) ? IsSparseT::Yes : IsSparseT::No, Index::Child{fldType, std::move(fldPath)}); } else { const auto fldType = scheme_.GetFieldType(fldPath); const auto isArray = scheme_.IsArray(fldPath); @@ -132,7 +132,7 @@ Ns::Ns(std::string name, RandomGenerator::ErrFactorType errorFactor) rndGen_.RndSparseIndex(fldType), Index::Child{fldType, std::move(fldPath)}); } if (const auto& idx = indexes_.back(); - !idx.IsArray() && idx.IsSparse() == IsSparse::No && + !idx.IsArray() && idx.IsSparse() == IsSparseT::No && std::get(idx.Content()).type != FieldType::Point) { // TODO remove point check after #1352 scalarIndexes.push_back(indexes_.size() - 1); } @@ -145,7 +145,7 @@ Ns::Ns(std::string name, RandomGenerator::ErrFactorType errorFactor) std::vector ii; for (size_t i = 0, s = indexes_.size(); i < s; ++i) { const auto& idx = indexes_[i]; - if (!idx.IsArray() && idx.IsSparse() == IsSparse::No && availablePkIndexType(idx.Type()) && + if (!idx.IsArray() && idx.IsSparse() == IsSparseT::No && availablePkIndexType(idx.Type()) && (std::holds_alternative(idx.Content()) || availablePkFieldType(std::get(idx.Content()).type))) { ii.push_back(i); } @@ -163,7 +163,7 @@ Ns::Ns(std::string name, RandomGenerator::ErrFactorType errorFactor) usedIndexNames.insert(name); } } - indexes_.emplace_back(std::move(name), rndGen_.RndPkIndexType({fldType}), IsArray::No, IsSparse::No, + indexes_.emplace_back(std::move(name), rndGen_.RndPkIndexType({fldType}), IsArrayT::No, IsSparseT::No, Index::Child{fldType, std::move(path)}); indexes_.back().SetPk(); } else { diff --git a/cpp_src/gtests/tests/fixtures/fuzzing/ns_scheme.cc b/cpp_src/gtests/tests/fixtures/fuzzing/ns_scheme.cc index 8c027dbc6..0a1c92829 100644 --- a/cpp_src/gtests/tests/fixtures/fuzzing/ns_scheme.cc +++ b/cpp_src/gtests/tests/fixtures/fuzzing/ns_scheme.cc @@ -77,13 +77,13 @@ size_t NsScheme::FieldsCount(const FieldPath& path) const noexcept { ref[path.back()].content); } -IsArray NsScheme::IsArray(const FieldPath& path) const noexcept { +IsArrayT NsScheme::IsArray(const FieldPath& path) const noexcept { if (path.empty()) return ns_.array; const Node::Children* ptr = &std::get(ns_.content); for (size_t i = 0, s = path.size() - 1; i < s; ++i) { assertrx(ptr->size() > path[i]); const auto& idx = (*ptr)[path[i]]; - if (idx.array == IsArray::Yes) return IsArray::Yes; + if (idx.array == IsArrayT::Yes) return IsArrayT::Yes; std::visit( reindexer::overloaded{[&ptr](const Node::Children& c) noexcept { ptr = &c; }, [](const Node::Child&) noexcept { assertrx(0); }}, idx.content); @@ -127,16 +127,16 @@ std::string NsScheme::GetJsonPath(const FieldPath& path) const noexcept { return res; } -void NsScheme::AddIndex(const FieldPath& path, size_t index, IsSparse isSparse) { +void NsScheme::AddIndex(const FieldPath& path, size_t index, IsSparseT isSparse) { assertrx(!path.empty()); - if (isSparse == IsSparse::No) { - ns_.sparse = IsSparse::No; + if (isSparse == IsSparseT::No) { + ns_.sparse = IsSparseT::No; } Node::Children* ptr = &std::get(ns_.content); for (size_t i = 0, s = path.size() - 1; i < s; ++i) { assertrx(ptr->size() > path[i]); - if (isSparse == IsSparse::No) { - (*ptr)[path[i]].sparse = IsSparse::No; + if (isSparse == IsSparseT::No) { + (*ptr)[path[i]].sparse = IsSparseT::No; } std::visit(reindexer::overloaded{[&ptr](Node::Children& c) noexcept { ptr = &c; }, [](Node::Child&) noexcept { assertrx(0); }}, (*ptr)[path[i]].content); @@ -148,14 +148,14 @@ void NsScheme::AddIndex(const FieldPath& path, size_t index, IsSparse isSparse) FieldPath NsScheme::AddRndPkField(RandomGenerator& rnd) { auto& children = std::get(ns_.content); children.emplace_back(Node{rnd.FieldName(generatedNames_), Node::Child{rnd.RndPkIndexFieldType()}}); - children.back().array = IsArray::No; - children.back().sparse = IsSparse::No; + children.back().array = IsArrayT::No; + children.back().sparse = IsSparseT::No; return {children.size() - 1}; } -void NsScheme::addIndex(Node& node, size_t index, IsSparse isSparse) { - if (isSparse == IsSparse::No) { - node.sparse = IsSparse::No; +void NsScheme::addIndex(Node& node, size_t index, IsSparseT isSparse) { + if (isSparse == IsSparseT::No) { + node.sparse = IsSparseT::No; } std::visit(reindexer::overloaded{[index](Node::Child& c) noexcept { c.indexes.push_back(index); }, [](Node::Children&) noexcept { assertrx(0); }}, @@ -175,14 +175,14 @@ void NsScheme::fillChildren(Node::Children& children, RandomGenerator& rnd, unsi children.back().array = rnd.RndArrayField(); } if (!canBeSparse && !rnd.RndErr()) { - children.back().sparse = IsSparse::No; + children.back().sparse = IsSparseT::No; } } else { children.emplace_back(Node{std::move(fName), Node::Child{type}}); if (type == FieldType::Point) { canBeSparse = false; canBeArray = false; - children.back().sparse = IsSparse::No; + children.back().sparse = IsSparseT::No; } if (canBeArray || rnd.RndErr()) { children.back().array = rnd.RndArrayField(); @@ -256,7 +256,7 @@ void NsScheme::toJson(reindexer::JsonBuilder& builder, const Node::Children& chi const std::vector& indexes) { for (const Node& n : children) { if (!rnd.NeedThisNode(n.sparse)) continue; - if (rnd.RndArrayField(n.array) == IsArray::Yes) { + if (rnd.RndArrayField(n.array) == IsArrayT::Yes) { auto arr = builder.Array(n.name); const size_t arrSize = rnd.ArraySize(); for (size_t i = 0; i < arrSize; ++i) { @@ -294,9 +294,9 @@ void NsScheme::Node::Dump(std::ostream& os, size_t offset) const { for (size_t i = 0; i <= offset; ++i) os << " "; os << "name: " << name << '\n'; for (size_t i = 0; i <= offset; ++i) os << " "; - os << "sparse: " << std::boolalpha << (sparse == IsSparse::Yes) << '\n'; + os << "sparse: " << std::boolalpha << (sparse == IsSparseT::Yes) << '\n'; for (size_t i = 0; i <= offset; ++i) os << " "; - os << "array: " << std::boolalpha << (array == IsArray::Yes) << '\n'; + os << "array: " << std::boolalpha << (array == IsArrayT::Yes) << '\n'; std::visit(reindexer::overloaded{[&](const Child& child) { for (size_t i = 0; i <= offset; ++i) os << " "; os << "type: " << child.type << '\n'; diff --git a/cpp_src/gtests/tests/fixtures/fuzzing/ns_scheme.h b/cpp_src/gtests/tests/fixtures/fuzzing/ns_scheme.h index a63a76e38..8123d726f 100644 --- a/cpp_src/gtests/tests/fixtures/fuzzing/ns_scheme.h +++ b/cpp_src/gtests/tests/fixtures/fuzzing/ns_scheme.h @@ -29,8 +29,8 @@ class NsScheme { std::string name; std::variant content; - IsSparse sparse{IsSparse::Yes}; - IsArray array{IsArray::No}; + IsSparseT sparse{IsSparseT::Yes}; + IsArrayT array{IsArrayT::No}; void Dump(std::ostream&, size_t offset) const; }; @@ -43,17 +43,17 @@ class NsScheme { bool IsStruct(const FieldPath&) const noexcept; bool IsPoint(const FieldPath&) const noexcept; bool IsTtl(const FieldPath&, const std::vector&) const noexcept; - enum IsArray IsArray(const FieldPath&) const noexcept; + IsArrayT IsArray(const FieldPath&) const noexcept; FieldType GetFieldType(const FieldPath&) const noexcept; void SetFieldType(const FieldPath&, FieldType) noexcept; std::string GetJsonPath(const FieldPath&) const noexcept; - void AddIndex(const FieldPath&, size_t index, IsSparse); + void AddIndex(const FieldPath&, size_t index, IsSparseT); void NewItem(reindexer::WrSerializer&, RandomGenerator&, const std::vector&); void Dump(std::ostream& os, size_t offset) const { ns_.Dump(os, offset); } FieldPath AddRndPkField(RandomGenerator&); private: - static void addIndex(Node&, size_t index, IsSparse); + static void addIndex(Node&, size_t index, IsSparseT); void fillChildren(Node::Children&, RandomGenerator&, unsigned level, bool& canBeArray, bool& canBeSparse); const Node::Children& findLastContainer(const FieldPath&) const noexcept; Node::Children& findLastContainer(const FieldPath&) noexcept; diff --git a/cpp_src/gtests/tests/fixtures/fuzzing/random_generator.cc b/cpp_src/gtests/tests/fixtures/fuzzing/random_generator.cc index e207a6667..82d85a68e 100644 --- a/cpp_src/gtests/tests/fixtures/fuzzing/random_generator.cc +++ b/cpp_src/gtests/tests/fixtures/fuzzing/random_generator.cc @@ -228,7 +228,7 @@ FieldPath RandomGenerator::RndScalarField(const NsScheme& nsScheme) { const int end = idx + size; while (idx < end) { res.back() = idx % size; - if (nsScheme.IsArray(res) == IsArray::No && !nsScheme.IsPoint(res)) break; + if (nsScheme.IsArray(res) == IsArrayT::No && !nsScheme.IsPoint(res)) break; ++idx; } if (idx == end) return {}; diff --git a/cpp_src/gtests/tests/fixtures/fuzzing/random_generator.h b/cpp_src/gtests/tests/fixtures/fuzzing/random_generator.h index 4960f28c3..bebb70490 100644 --- a/cpp_src/gtests/tests/fixtures/fuzzing/random_generator.h +++ b/cpp_src/gtests/tests/fixtures/fuzzing/random_generator.h @@ -60,20 +60,20 @@ class RandomGenerator { IndexType RndIndexType(const std::vector&); IndexType RndPkIndexType(const std::vector&); IndexType RndIndexType(IndexType); - IsArray RndArrayField() { return RndBool(0.2) ? IsArray::Yes : IsArray::No; } - IsArray RndArrayField(IsArray array) { + IsArrayT RndArrayField() { return RndBool(0.2) ? IsArrayT::Yes : IsArrayT::No; } + IsArrayT RndArrayField(IsArrayT array) { if (RndErr()) { - return array == IsArray::Yes ? IsArray::No : IsArray::Yes; + return array == IsArrayT::Yes ? IsArrayT::No : IsArrayT::Yes; } return array; } size_t ArraySize(); bool PkIndex(bool pk) { return RndErr() ? RndBool(0.5) : pk; } - IsSparse RndSparseIndex(FieldType fldType) { + IsSparseT RndSparseIndex(FieldType fldType) { const bool couldBeSparse = fldType != FieldType::Struct && fldType != FieldType::Uuid; // TODO remove uuid #1470 - return (couldBeSparse ? RndBool(0.2) : RndErr()) ? IsSparse::Yes : IsSparse::No; + return (couldBeSparse ? RndBool(0.2) : RndErr()) ? IsSparseT::Yes : IsSparseT::No; } - bool RndSparseIndex(IsSparse isSparse) { return (isSparse == IsSparse::Yes) != RndErr(); } + bool RndSparseIndex(IsSparseT isSparse) { return (isSparse == IsSparseT::Yes) != RndErr(); } bool DenseIndex() { return RndBool(0.2); } int64_t ExpiredIndex() { return RndInt(0, 100'000); } // TODO size_t IndexesCount(); @@ -137,7 +137,7 @@ class RandomGenerator { return err; } char RndChar() { return rndChar_(gen_); } - bool NeedThisNode(IsSparse sparse) { return sparse == IsSparse::Yes ? RndBool(0.5) : !RndErr(); } + bool NeedThisNode(IsSparseT sparse) { return sparse == IsSparseT::Yes ? RndBool(0.5) : !RndErr(); } int RndIntValue() { enum Size : uint8_t { Short, Long, END = Long }; switch (RndWhich()) { diff --git a/cpp_src/gtests/tests/fixtures/fuzzing/types.h b/cpp_src/gtests/tests/fixtures/fuzzing/types.h index db97087c6..98ec500a8 100644 --- a/cpp_src/gtests/tests/fixtures/fuzzing/types.h +++ b/cpp_src/gtests/tests/fixtures/fuzzing/types.h @@ -23,7 +23,7 @@ enum class IndexType { Store, Hash, Tree, Ttl, FastFT, FuzzyFT, RTree, END = RTr std::string_view ToText(IndexType); std::ostream& operator<<(std::ostream&, IndexType); -enum class IsArray : bool { Yes = true, No = false }; -enum class IsSparse : bool { Yes = true, No = false }; +enum class IsArrayT : bool { Yes = true, No = false }; +enum class IsSparseT : bool { Yes = true, No = false }; } // namespace fuzzing diff --git a/cpp_src/gtests/tests/fixtures/grpcclient_api.h b/cpp_src/gtests/tests/fixtures/grpcclient_api.h index 98b05c866..7a772dcd9 100644 --- a/cpp_src/gtests/tests/fixtures/grpcclient_api.h +++ b/cpp_src/gtests/tests/fixtures/grpcclient_api.h @@ -17,6 +17,7 @@ class GrpcClientApi : public ReindexerApi { public: void SetUp() { + reindexer::fs::RmDirAll(kStoragePath); YAML::Node y; y["storage"]["path"] = kStoragePath; y["logger"]["loglevel"] = "none"; @@ -27,7 +28,6 @@ class GrpcClientApi : public ReindexerApi { y["net"]["rpcaddr"] = "0.0.0.0:4443"; y["net"]["grpc"] = true; - reindexer::fs::RmDirAll(kStoragePath); auto err = srv_.InitFromYAML(YAML::Dump(y)); EXPECT_TRUE(err.ok()) << err.what(); @@ -42,7 +42,7 @@ class GrpcClientApi : public ReindexerApi { std::this_thread::sleep_for(std::chrono::milliseconds(20)); } - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 10; i++) { auto channel = grpc::CreateChannel("127.0.0.1:16534", grpc::InsecureChannelCredentials()); if (channel->WaitForConnected(std::chrono::system_clock::now() + std::chrono::seconds(1))) { rx_ = reindexer::grpc::Reindexer::NewStub(channel); @@ -351,7 +351,7 @@ class GrpcClientApi : public ReindexerApi { std::unique_ptr rx_; uint64_t lastLsn_ = 0, lastRowId_ = INT_MAX; - const std::string kStoragePath = "/tmp/reindex_grpc_test/"; + const std::string kStoragePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex_grpc_test"); }; #endif diff --git a/cpp_src/gtests/tests/fixtures/join_on_conditions_api.h b/cpp_src/gtests/tests/fixtures/join_on_conditions_api.h index 8834ba94e..5173b168d 100644 --- a/cpp_src/gtests/tests/fixtures/join_on_conditions_api.h +++ b/cpp_src/gtests/tests/fixtures/join_on_conditions_api.h @@ -4,7 +4,7 @@ class JoinOnConditionsApi : public JoinSelectsApi { public: - void SetUp() override { JoinSelectsApi::Init("/tmp/join_on_conditions_test/"); } + void SetUp() override { JoinSelectsApi::Init(reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "join_on_conditions_test")); } void CreateCondSetTable(const std::string& leftNs, const std::string& rightNs, const std::vector& leftNsData, const std::vector>& rightNsData) { diff --git a/cpp_src/gtests/tests/fixtures/join_selects_api.h b/cpp_src/gtests/tests/fixtures/join_selects_api.h index cdf0f9189..084e2b307 100644 --- a/cpp_src/gtests/tests/fixtures/join_selects_api.h +++ b/cpp_src/gtests/tests/fixtures/join_selects_api.h @@ -19,7 +19,7 @@ class JoinSelectsApi : public ReindexerApi { using QueryResultRow = std::map; using QueryResultRows = std::map; - void Init(const std::string& dbName = "/tmp/join_test/") { + void Init(const std::string& dbName = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "join_test")) { Error err; reindexer::fs::RmDirAll(dbName); @@ -398,8 +398,7 @@ class JoinSelectsApi : public ReindexerApi { EXPECT_EQ(err.what(), expectedText) << sql; } { - Query q; - q.FromSQL(sql); + Query q = Query::FromSQL(sql); auto err = rt.reindexer->Select(q, qr); EXPECT_EQ(err.code(), expectedCode) << sql; EXPECT_EQ(err.what(), expectedText) << sql; diff --git a/cpp_src/gtests/tests/fixtures/msgpack_cproto_api.h b/cpp_src/gtests/tests/fixtures/msgpack_cproto_api.h index ce7f7b985..6661f5867 100644 --- a/cpp_src/gtests/tests/fixtures/msgpack_cproto_api.h +++ b/cpp_src/gtests/tests/fixtures/msgpack_cproto_api.h @@ -20,7 +20,7 @@ class MsgPackCprotoApi : public ReindexerApi { void SetUp() { reindexer::fs::RmDirAll(kDbPath); YAML::Node y; - y["storage"]["path"] = "/tmp/reindex/" + kDbPath; + y["storage"]["path"] = kDbPath; y["logger"]["loglevel"] = "none"; y["logger"]["rpclog"] = "none"; y["logger"]["serverlog"] = "none"; @@ -40,7 +40,7 @@ class MsgPackCprotoApi : public ReindexerApi { } client_.reset(new reindexer::client::RPCClientMock()); - err = client_->Connect("cproto://127.0.0.1:25677/" + kDbPath, reindexer::client::ConnectOpts().CreateDBIfMissing()); + err = client_->Connect("cproto://127.0.0.1:25677/" + kDbName, reindexer::client::ConnectOpts().CreateDBIfMissing()); ASSERT_TRUE(err.ok()) << err.what(); err = client_->OpenNamespace(default_namespace, ctx_, StorageOpts().CreateIfMissing()); @@ -81,11 +81,12 @@ class MsgPackCprotoApi : public ReindexerApi { void TearDown() { if (server_.IsRunning()) { server_.Stop(); - if (serverThread_->joinable()) { - serverThread_->join(); - } } - client_->Stop(); + client_.reset(); + if (serverThread_->joinable()) { + serverThread_->join(); + } + serverThread_.reset(); } void checkItem(reindexer::client::QueryResults::Iterator& it) { @@ -105,7 +106,8 @@ class MsgPackCprotoApi : public ReindexerApi { } protected: - const std::string kDbPath = "cproto_msgpack_test"; + const std::string kDbName = "cproto_msgpack_test"; + const std::string kDbPath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex/" + kDbName); const std::string kFieldId = "id"; const std::string kFieldA1 = "a1"; const std::string kFieldA2 = "a2"; diff --git a/cpp_src/gtests/tests/fixtures/queries_api.cc b/cpp_src/gtests/tests/fixtures/queries_api.cc index a1be92c4c..5211177a0 100644 --- a/cpp_src/gtests/tests/fixtures/queries_api.cc +++ b/cpp_src/gtests/tests/fixtures/queries_api.cc @@ -114,13 +114,11 @@ void QueriesApi::CheckMergeQueriesWithAggregation() { double c4; AggSelect(Query{testSimpleNs}.Aggregate(AggCount, {}), AggCount, c4); double c3; - Query q3; - q3.FromSQL(fmt::sprintf("SELECT count(*) FROM %s MERGE (SELECT * FROM %s)", default_namespace, joinNs)); + Query q3 = Query::FromSQL(fmt::sprintf("SELECT count(*) FROM %s MERGE (SELECT * FROM %s)", default_namespace, joinNs)); AggSelect(q3, AggCount, c3); double c5; - Query q5; - q5.FromSQL(fmt::sprintf("SELECT count(*) FROM %s MERGE (SELECT * FROM %s) MERGE (SELECT * FROM %s)", default_namespace, joinNs, - testSimpleNs)); + Query q5 = Query::FromSQL(fmt::sprintf("SELECT count(*) FROM %s MERGE (SELECT * FROM %s) MERGE (SELECT * FROM %s)", + default_namespace, joinNs, testSimpleNs)); AggSelect(q5, AggCount, c5); { QueryResults qr; @@ -141,7 +139,8 @@ void QueriesApi::CheckMergeQueriesWithAggregation() { double c4; AggSelect(Query{testSimpleNs}.Aggregate(AggCountCached, {}), AggCountCached, c4); double c5; - AggSelect(Query{default_namespace}.Aggregate(AggCountCached, {}).Merge(Query{joinNs}).Merge(Query{testSimpleNs}), AggCountCached, c5); + AggSelect(Query{default_namespace}.Aggregate(AggCountCached, {}).Merge(Query{joinNs}).Merge(Query{testSimpleNs}), AggCountCached, + c5); ASSERT_EQ(c1 + c2, c3); ASSERT_EQ(c1 + c2 + c4, c5); } @@ -212,13 +211,13 @@ void QueriesApi::CheckMergeQueriesWithAggregation() { QueryResults qr; Error err = rt.reindexer->Select(Query{default_namespace}.Merge(Query{joinNs}.ReqTotal()), qr); EXPECT_FALSE(err.ok()); - EXPECT_EQ(err.what(), "Aggregations in inner merge query is not allowed"); + EXPECT_EQ(err.what(), "Aggregations in inner merge query are not allowed"); } { QueryResults qr; Error err = rt.reindexer->Select(Query{default_namespace}.Merge(Query{joinNs}.CachedTotal()), qr); EXPECT_FALSE(err.ok()); - EXPECT_EQ(err.what(), "Aggregations in inner merge query is not allowed"); + EXPECT_EQ(err.what(), "Aggregations in inner merge query are not allowed"); } // checking the work of several aggregate functions with the merge query { @@ -535,3 +534,1083 @@ void QueriesApi::CheckUUIDQueries() { } } } + +void QueriesApi::checkSqlQuery(std::string_view sqlQuery, Query&& checkQuery) { + QueryResults sqlQr; + Error err = rt.reindexer->Select(sqlQuery, sqlQr); + ASSERT_TRUE(err.ok()) << err.what(); + + QueryResults checkQr; + err = rt.reindexer->Select(checkQuery, checkQr); + ASSERT_TRUE(err.ok()) << err.what(); + + CompareQueryResults(sqlQuery, sqlQr, checkQr); + Verify(checkQr, std::move(checkQuery), *rt.reindexer); +} + +void QueriesApi::CheckSqlQueries() { + using namespace std::string_literals; + using namespace std::string_view_literals; + using reindexer::randPoint; + using reindexer::randBinDouble; + + checkSqlQuery("SELECT ID, Year, Genre FROM test_namespace WHERE year > '2016' ORDER BY year DESC LIMIT 10000000"sv, + Query(default_namespace, 0, 10000000).Where(kFieldNameYear, CondGt, 2016).Sort(kFieldNameYear, true)); + + checkSqlQuery("SELECT ID, Year, Genre FROM test_namespace WHERE genre IN ('1',2,'3') ORDER BY year DESC LIMIT 10000000"sv, + Query(default_namespace, 0, 10000000).Where(kFieldNameGenre, CondSet, {1, 2, 3}).Sort(kFieldNameYear, true)); + + const std::string likePattern = RandLikePattern(); + checkSqlQuery("SELECT ID, Year, Genre FROM test_namespace WHERE name LIKE '"s + likePattern + "' ORDER BY year DESC LIMIT 10000000"s, + Query(default_namespace, 0, 10000000).Where(kFieldNameName, CondLike, likePattern).Sort(kFieldNameYear, true)); + + checkSqlQuery("SELECT FACET(ID, Year ORDER BY ID DESC ORDER BY Year ASC LIMIT 20 OFFSET 1) FROM test_namespace LIMIT 10000000"sv, + Query(default_namespace, 0, 10000000) + .Aggregate(AggFacet, {kFieldNameId, kFieldNameYear}, {{kFieldNameId, true}, {kFieldNameYear, false}}, 20, 1)); + + checkSqlQuery("SELECT ID FROM test_namespace WHERE name LIKE '"s + likePattern + + "' AND (genre IN ('1', '2', '3') AND year > '2016' ) OR age IN ('1', '2', '3', '4') LIMIT 10000000"s, + Query(default_namespace, 0, 10000000) + .Where(kFieldNameName, CondLike, likePattern) + .OpenBracket() + .Where(kFieldNameGenre, CondSet, {1, 2, 3}) + .Where(kFieldNameYear, CondGt, 2016) + .CloseBracket() + .Or() + .Where(kFieldNameAge, CondSet, {1, 2, 3, 4})); + + checkSqlQuery(fmt::sprintf("SELECT ID FROM test_namespace ORDER BY '%s + %s * 5' DESC LIMIT 10000000", kFieldNameYear, kFieldNameId), + Query(default_namespace, 0, 10000000).Sort(kFieldNameYear + std::string(" + ") + kFieldNameId + " * 5", true)); + + checkSqlQuery(fmt::sprintf("SELECT ID FROM test_namespace ORDER BY '%s + %s * 5' DESC ORDER BY '2 * %s / (1 + %s)' ASC LIMIT 10000000", + kFieldNameYear, kFieldNameId, kFieldNameGenre, kFieldNameIsDeleted), + Query(default_namespace, 0, 10000000) + .Sort(kFieldNameYear + std::string(" + ") + kFieldNameId + " * 5", true) + .Sort(std::string("2 * ") + kFieldNameGenre + " / (1 + " + kFieldNameIsDeleted + ')', false)); + + // Checks that SQL queries with DWithin and sort by Distance work and compares the result with the result of corresponding C++ query + reindexer::Point point = randPoint(10); + double distance = randBinDouble(0, 1); + checkSqlQuery(fmt::sprintf("SELECT * FROM %s WHERE ST_DWithin(%s, %s, %s);", geomNs, kFieldNamePointNonIndex, pointToSQL(point), + toString(distance)), + Query(geomNs).DWithin(kFieldNamePointNonIndex, point, distance)); + + point = randPoint(10); + distance = randBinDouble(0, 1); + checkSqlQuery(fmt::sprintf("SELECT * FROM %s WHERE ST_DWithin(%s, %s, %s) ORDER BY 'ST_Distance(%s, %s)';", geomNs, pointToSQL(point), + kFieldNamePointNonIndex, toString(distance), kFieldNamePointLinearRTree, pointToSQL(point, true)), + Query(geomNs) + .DWithin(kFieldNamePointNonIndex, point, distance) + .Sort(std::string("ST_Distance(") + kFieldNamePointLinearRTree + ", " + pointToSQL(point) + ')', false)); + + checkSqlQuery(fmt::sprintf("SELECT * FROM %s WHERE %s >= %s;", default_namespace, kFieldNameGenre, kFieldNameRate), + Query(default_namespace).WhereBetweenFields(kFieldNameGenre, CondGe, kFieldNameRate)); +} + +void QueriesApi::checkDslQuery(std::string_view dslQuery, Query&& checkQuery) { + Query parsedQuery; + Error err = parsedQuery.FromJSON(dslQuery); + ASSERT_TRUE(err.ok()) << "Query: " << dslQuery << "; err: " << err.what(); + + QueryResults dslQr; + err = rt.reindexer->Select(parsedQuery, dslQr); + ASSERT_TRUE(err.ok()) << "Query: " << dslQuery << "; err: " << err.what(); + + QueryResults checkQr; + err = rt.reindexer->Select(checkQuery, checkQr); + ASSERT_TRUE(err.ok()) << "Query: " << dslQuery << "; err: " << err.what(); + + CompareQueryResults(dslQuery, dslQr, checkQr); + Verify(checkQr, std::move(checkQuery), *rt.reindexer); +} + +// Checks that DSL queries works and compares the result with the result of corresponding C++ query +void QueriesApi::CheckDslQueries() { + using namespace std::string_literals; + using reindexer::randPoint; + using reindexer::randBinDouble; + using reindexer::double_to_str; + + auto point{randPoint(10)}; + auto distance = randBinDouble(0, 1); + checkDslQuery( + fmt::sprintf( + R"({"namespace":"%s","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"dwithin","field":"%s","value":[[%s, %s], %s]}],"merge_queries":[],"aggregations":[]})", + geomNs, kFieldNamePointLinearRTree, double_to_str(point.X()), double_to_str(point.Y()), double_to_str(distance)), + Query(geomNs).DWithin(kFieldNamePointLinearRTree, point, distance)); + + point = randPoint(10); + distance = randBinDouble(0, 1); + checkDslQuery( + fmt::sprintf( + R"({"namespace":"%s","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"dwithin","field":"%s","value":[%s,[%s,%s]]}],"merge_queries":[],"aggregations":[]})", + geomNs, kFieldNamePointLinearRTree, double_to_str(distance), double_to_str(point.X()), double_to_str(point.Y())), + Query(geomNs).DWithin(kFieldNamePointLinearRTree, point, distance)); + + checkDslQuery( + fmt::sprintf( + R"({"namespace":"%s","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"gt","first_field":"%s","second_field":"%s"}],"merge_queries":[],"aggregations":[]})", + default_namespace, kFieldNameStartTime, kFieldNamePackages), + Query{default_namespace}.WhereBetweenFields(kFieldNameStartTime, CondGt, kFieldNamePackages)); + + checkDslQuery( + fmt::sprintf( + R"({"namespace":"%s","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"SET","field":"%s","Value":["1", " 10 ", "100 ", " 1000"]}],"merge_queries":[],"aggregations":[]})", + default_namespace, kFieldNameId), + Query{default_namespace}.Where(kFieldNameId, CondSet, {1, 10, 100, 1000})); +} + +void QueriesApi::CheckStandartQueries() { + try { + using namespace std::string_literals; + static const std::vector sortIdxs = { + "", + kFieldNameName, + kFieldNameYear, + kFieldNameRate, + kFieldNameBtreeIdsets, + std::string{"-2.5 * "} + kFieldNameRate + " / (" + kFieldNameYear + " + " + kFieldNameId + ')'}; + static const std::vector distincts = {"", kFieldNameYear, kFieldNameRate}; + static const std::vector sortOrders = {true, false}; + + for ([[maybe_unused]] const bool sortOrder : sortOrders) { + for ([[maybe_unused]] const auto& sortIdx : sortIdxs) { + for ([[maybe_unused]] const std::string& distinct : distincts) { + [[maybe_unused]] const int randomAge = rand() % 50; + [[maybe_unused]] const int randomGenre = rand() % 50; + [[maybe_unused]] const int randomGenreUpper = rand() % 100; + [[maybe_unused]] const int randomGenreLower = rand() % 100; + + ExecuteAndVerify(Query(default_namespace).Distinct(distinct.c_str()).Sort(sortIdx, sortOrder).Limit(1)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondEq, randomGenre) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondEq, std::to_string(randomGenre)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameName, CondEq, RandString()) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameRate, CondEq, (rand() % 100) / 10.0) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameRate, CondEq, std::to_string((rand() % 100) / 10.0)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondGt, randomGenre) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameName, CondGt, RandString()) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameRate, CondGt, (rand() % 100) / 10.0) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondLt, randomGenre) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondLt, std::to_string(randomGenre)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameName, CondLt, RandString()) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameRate, CondLt, (rand() % 100) / 10.0) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameRate, CondLt, std::to_string((rand() % 100) / 10.0)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameBtreeIdsets, CondLt, static_cast(rand() % 10000)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameBtreeIdsets, CondGt, static_cast(rand() % 10000)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameBtreeIdsets, CondEq, static_cast(rand() % 10000)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondRange, {randomGenreLower, randomGenreUpper}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameName, CondRange, {RandString(), RandString()}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameName, CondLike, RandLikePattern()) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameRate, CondRange, + {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNamePackages, CondSet, RandIntVector(10, 10000, 50)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNamePackages, CondAllSet, RandIntVector(2, 10000, 50)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNamePackages, CondAllSet, 10000 + rand() % 50) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + // check substituteCompositIndexes + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameAge, CondEq, randomAge) + .Where(kFieldNameGenre, CondEq, randomGenre) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) + .Where(kFieldNameGenre, CondEq, randomGenre) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameAge, CondAllSet, RandIntVector(1, 0, 50)) + .Where(kFieldNameGenre, CondEq, randomGenre) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) + .Where(kFieldNameGenre, CondSet, RandIntVector(10, 0, 50)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 20)) + .Where(kFieldNameGenre, CondSet, RandIntVector(10, 0, 50)) + .Where(kFieldNameAge, CondSet, RandIntVector(10, 30, 50)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 20)) + .Where(kFieldNameGenre, CondEq, randomGenre) + .Where(kFieldNameAge, CondSet, RandIntVector(10, 30, 50)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + // end of check substituteCompositIndexes + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNamePackages, CondEmpty, VariantArray{}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameName, CondRange, {RandString(), RandString()}) + .Distinct(distinct.c_str()) + .Sort(kFieldNameYear, true) + .Sort(kFieldNameName, false) + .Sort(kFieldNameLocation, true)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameName, CondRange, {RandString(), RandString()}) + .Distinct(distinct.c_str()) + .Sort(kFieldNameGenre, true) + .Sort(kFieldNameActor, false) + .Sort(kFieldNameRate, true) + .Sort(kFieldNameLocation, false)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameName, CondLike, RandLikePattern()) + .Distinct(distinct.c_str()) + .Sort(kFieldNameGenre, true) + .Sort(kFieldNameActor, false) + .Sort(kFieldNameRate, true) + .Sort(kFieldNameLocation, false)); + + ExecuteAndVerify(Query(default_namespace).Sort(kFieldNameGenre, true, {10, 20, 30})); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNamePackages, CondAny, VariantArray{}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify( + Query(default_namespace).Where(kFieldNameIsDeleted, CondEq, 1).Distinct(distinct.c_str()).Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Where(kFieldNameGenre, CondEq, 5) + .Where(kFieldNameAge, CondEq, 3) + .Where(kFieldNameYear, CondGe, 2010) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Debug(LogTrace)); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondEq, 5) + .Where(kFieldNameAge, CondEq, 3) + .Where(kFieldNameGenre, CondEq, 5) + .Where(kFieldNameAge, CondEq, 3) + .OpenBracket() + .Where(kFieldNameYear, CondGe, 2010) + .CloseBracket() + .Or() + .Where(kFieldNameYear, CondGe, 2010)); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameYear, CondGt, 2002) + .Where(kFieldNameGenre, CondEq, 4) + .Where(kFieldNameAge, CondEq, 3) + .Where(kFieldNameIsDeleted, CondEq, 3) + .Or() + .Where(kFieldNameYear, CondGt, 2001) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Debug(LogTrace)); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameAge, CondSet, {1, 2, 3, 4}) + .Where(kFieldNameId, CondEq, rand() % 5000) + .Where(kFieldNameTemp, CondEq, "") + .Where(kFieldNameIsDeleted, CondEq, 1) + .Or() + .Where(kFieldNameYear, CondGt, 2001) + .Debug(LogTrace)); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondSet, {5, 1, 7}) + .Where(kFieldNameYear, CondLt, 2010) + .Where(kFieldNameGenre, CondEq, 3) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Or() + .Where(kFieldNamePackages, CondEmpty, VariantArray{}) + .Debug(LogTrace)); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondSet, {5, 1, 7}) + .Where(kFieldNameYear, CondLt, 2010) + .Or() + .Where(kFieldNamePackages, CondAny, VariantArray{}) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Debug(LogTrace)); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondEq, 5) + .Or() + .Where(kFieldNameGenre, CondEq, 6) + .Where(kFieldNameYear, CondRange, {2001, 2020}) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50))); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondEq, 5) + .Or() + .Where(kFieldNameGenre, CondEq, 6) + .Not() + .Where(kFieldNameName, CondLike, RandLikePattern()) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50))); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameActor, CondEq, RandString())); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Not() + .Where(kFieldNameGenre, CondEq, 5) + .Where(kFieldNameYear, CondRange, {2001, 2020}) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50))); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondEq, 5) + .Not() + .Where(kFieldNameYear, CondRange, {2001, 2020}) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50))); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Not() + .Where(kFieldNameYear, CondEq, 10)); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(kFieldNameNumeric, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameNumeric, CondGt, std::to_string(5))); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(kFieldNameNumeric, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameNumeric, CondLt, std::to_string(600))); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondEq, 5) + .Or() + .OpenBracket() + .Where(kFieldNameGenre, CondLt, 6) + .Where(kFieldNameYear, CondRange, {2001, 2020}) + .CloseBracket() + .Not() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .OpenBracket() + .Where(kFieldNameNumeric, CondLt, std::to_string(600)) + .Or() + .OpenBracket() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Where(kFieldNameName, CondLike, RandLikePattern()) + .CloseBracket() + .Or() + .Where(kFieldNameYear, CondEq, 10) + .CloseBracket()); + + ExecuteAndVerify(Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondEq, 5) + .Not() + .OpenBracket() + .Where(kFieldNameYear, CondRange, {2001, 2020}) + .Or() + .Where(kFieldNameName, CondLike, RandLikePattern()) + .CloseBracket() + .Or() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .OpenBracket() + .Where(kFieldNameNumeric, CondLt, std::to_string(600)) + .Not() + .OpenBracket() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Where(kFieldNameGenre, CondLt, 6) + .CloseBracket() + .Or() + .Where(kFieldNameYear, CondEq, 10) + .CloseBracket()); + + ExecuteAndVerify( + Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameNumeric, CondRange, {std::to_string(rand() % 100), std::to_string(rand() % 100 + 500)})); + + ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameName, CondEq, "SSS")); + ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameYear, CondEq, 2002)); + ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameYear, CondEq, 2002).Not().Where(kFieldNameName, CondEq, 2002)); + ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameName, CondEq, "SSS").Not().Where(kFieldNameYear, CondEq, 2002)); + ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameName, CondEq, "SSS").Not().Where(kFieldNameYear, CondEq, 1989)); + ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameYear, CondEq, 2002).Not().Where(kFieldNameName, CondEq, "MMM")); + + ExecuteAndVerify(Query(default_namespace) + .ReqTotal() + .Distinct(distinct) + .Sort(sortIdx, sortOrder) + .WhereComposite(kCompositeFieldAgeGenre, CondLe, {{Variant(27), Variant(10000)}})); + + ExecuteAndVerify(Query(default_namespace) + .ReqTotal() + .Distinct(distinct) + .Sort(kFieldNameAge + " + "s + kFieldNameId, sortOrder) + .Sort(kFieldNameRate + " * "s + kFieldNameGenre, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .ReqTotal() + .Distinct(distinct) + .Sort(sortIdx, sortOrder) + .WhereComposite(kCompositeFieldAgeGenre, CondEq, {{Variant(rand() % 10), Variant(rand() % 50)}})); + + ExecuteAndVerify(Query(default_namespace) + .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, Query(joinNs)) + .Distinct(distinct) + .Sort(joinNs + '.' + kFieldNameId, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, Query(joinNs)) + .Distinct(distinct) + .Sort(joinNs + '.' + kFieldNameName, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, Query(joinNs)) + .Distinct(distinct) + .Sort(joinNs + '.' + kFieldNameId + " * " + joinNs + '.' + kFieldNameGenre + + (sortIdx.empty() || (sortIdx == kFieldNameName) ? "" : (" + " + sortIdx)), + sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, + Query(joinNs) + .Where(kFieldNameId, CondSet, RandIntVector(20, 0, 100)) + .Sort(kFieldNameId + " + "s + kFieldNameYear, sortOrder)) + .Distinct(distinct)); + + ExecuteAndVerify( + Query(default_namespace) + .InnerJoin( + kFieldNameYear, kFieldNameYear, CondEq, + Query(joinNs).Where(kFieldNameYear, CondGe, 1925).Sort(kFieldNameId + " + "s + kFieldNameYear, sortOrder)) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .InnerJoin(kFieldNameYear, kFieldNameYear, randCond(), + Query(joinNs).Where(kFieldNameYear, CondGe, 2000 + rand() % 210)) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .InnerJoin(kFieldNameYear, kFieldNameYear, randCond(), + Query(joinNs).Where(kFieldNameYear, CondLe, 2000 + rand() % 210).Limit(rand() % 10)) + .Distinct(distinct)); + ExecuteAndVerify( + Query(default_namespace) + .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210) /*.Offset(rand() % 10)*/) + .On(kFieldNameYear, randCond(), kFieldNameYear) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameYearSparse, CondEq, std::to_string(2000 + rand() % 60)) + .Distinct(distinct)); + ExecuteAndVerify( + Query(default_namespace) + .InnerJoin(kFieldNameYear, kFieldNameYear, randCond(), + Query(joinNs).Where(kFieldNameYear, CondLt, 2000 + rand() % 210).Sort(kFieldNameName, sortOrder)) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210)) + .OpenBracket() + .On(kFieldNameYear, randCond(), kFieldNameYear) + .Or() + .On(kFieldNameName, CondEq, kFieldNameName) + .CloseBracket() + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210)) + .OpenBracket() + .On(kFieldNameYear, randCond(), kFieldNameYear) + .Or() + .On(kFieldNameName, CondEq, kFieldNameName) + .On(kFieldNameAge, randCond(), kFieldNameAge) + .Not() + .On(kFieldNameYear, randCond(), kFieldNameYear) + .CloseBracket() + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210)) + .OpenBracket() + .On(kFieldNameYearSparse, CondLe, kFieldNameYearSparse) + .Or() + .On(kFieldNameName, CondEq, kFieldNameName) + .Or() + .On(kFieldNameAge, randCond(), kFieldNameAge) + .Not() + .On(kFieldNameYear, randCond(), kFieldNameYear) + .CloseBracket() + .Distinct(distinct)); + ExecuteAndVerify( + Query(default_namespace) + .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210).Limit(rand() % 100)) + .OpenBracket() + .On(kFieldNameYear, randCond(), kFieldNameYear) + .Or() + .On(kFieldNameName, CondEq, kFieldNameName) + .Or() + .On(kFieldNameAge, randCond(), kFieldNameAge) + .CloseBracket() + .Or() + .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondLt, 2000 + rand() % 210).Limit(rand() % 100)) + .OpenBracket() + .On(kFieldNameYear, randCond(), kFieldNameYear) + .Or() + .On(kFieldNameName, CondEq, kFieldNameName) + .Or() + .On(kFieldNameAge, randCond(), kFieldNameAge) + .CloseBracket() + .Join(OrInnerJoin, Query(joinNs).Where(kFieldNameYear, CondEq, 2000 + rand() % 210).Limit(rand() % 100)) + .OpenBracket() + .On(kFieldNameYear, randCond(), kFieldNameYear) + .Or() + .On(kFieldNameName, CondEq, kFieldNameName) + .Or() + .On(kFieldNameAge, randCond(), kFieldNameAge) + .CloseBracket() + .Or() + .Where(kFieldNameId, CondSet, RandIntVector(20, 0, 100)) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .WhereBetweenFields(kFieldNameGenre, CondEq, kFieldNameAge) + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .WhereBetweenFields(kFieldNameName, CondLike, kFieldNameActor) + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .WhereBetweenFields(kFieldNamePackages, CondGt, kFieldNameStartTime) + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify( + Query(compositeIndexesNs).WhereBetweenFields(kCompositeFieldPriceTitle, CondEq, kCompositeFieldPagesTitle)); + ExecuteAndVerify(Query(default_namespace) + .Not() + .Where(kFieldNameIsDeleted, CondEq, true) + .Or() + .Where(kFieldNameYear, CondGt, 2001) + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondEq, 5) + .Or() + .OpenBracket() + .Where(kFieldNameGenre, CondEq, 4) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .CloseBracket() + .Not() + .Where(kFieldNameYear, CondRange, {2001, 2010}) + .OpenBracket() + .Where(kFieldNameRate, CondRange, + {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) + .Or() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Not() + .OpenBracket() + .OpenBracket() + .OpenBracket() + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) + .Or() + .Where(kFieldNameId, CondEq, rand() % 5000) + .Where(kFieldNameTemp, CondEq, "") + .CloseBracket() + .Or() + .OpenBracket() + .Where(kFieldNameTemp, CondEq, "") + .Not() + .Where(kFieldNameIsDeleted, CondEq, true) + .Or() + .Where(kFieldNameYear, CondGt, 2001) + .CloseBracket() + .CloseBracket() + .CloseBracket() + .CloseBracket() + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondEq, 5) + .Or() + .OpenBracket() + .Where(kFieldNameGenre, CondEq, 4) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .CloseBracket() + .Not() + .Where(kFieldNameYear, CondRange, {2001, 2010}) + .OpenBracket() + .Where(kFieldNameRate, CondRange, + {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) + .Or() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Not() + .OpenBracket() + .OpenBracket() + .OpenBracket() + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) + .Or() + .Where(kFieldNameId, CondEq, rand() % 5000) + .Where(kFieldNameTemp, CondEq, "") + .CloseBracket() + .Or() + .OpenBracket() + .Where(kFieldNameTemp, CondEq, "") + .Not() + .OpenBracket() + .Where(kFieldNameIsDeleted, CondEq, true) + .CloseBracket() + .Or() + .Where(kFieldNameYear, CondGt, 2001) + .CloseBracket() + .CloseBracket() + .CloseBracket() + .CloseBracket() + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondEq, 5) + .Or() + .OpenBracket() + .Where(kFieldNameGenre, CondEq, 4) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .CloseBracket() + .Not() + .Where(kFieldNameYear, CondRange, {2001, 2010}) + .OpenBracket() + .Where(kFieldNameRate, CondRange, + {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) + .Or() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Not() + .OpenBracket() + .OpenBracket() + .OpenBracket() + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) + .Or() + .Where(kFieldNameId, CondEq, rand() % 5000) + .Where(kFieldNameTemp, CondEq, "") + .CloseBracket() + .Or() + .OpenBracket() + .Where(kFieldNameTemp, CondEq, "") + .OpenBracket() + .Not() + .Where(kFieldNameIsDeleted, CondEq, true) + .CloseBracket() + .Or() + .Where(kFieldNameYear, CondGt, 2001) + .CloseBracket() + .CloseBracket() + .CloseBracket() + .CloseBracket() + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondEq, 5) + .Or() + .OpenBracket() + .Where(kFieldNameGenre, CondEq, 4) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .CloseBracket() + .Not() + .Where(kFieldNameYear, CondRange, {2001, 2010}) + .OpenBracket() + .Where(kFieldNameRate, CondRange, + {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) + .Or() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Not() + .OpenBracket() + .OpenBracket() + .OpenBracket() + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) + .Or() + .Where(kFieldNameId, CondEq, rand() % 5000) + .Where(kFieldNameTemp, CondEq, "") + .CloseBracket() + .Or() + .OpenBracket() + .Where(kFieldNameTemp, CondEq, "") + .OpenBracket() + .Not() + .Where(kFieldNameIsDeleted, CondEq, true) + .Or() + .Where(kFieldNameYear, CondGt, 2001) + .CloseBracket() + .CloseBracket() + .CloseBracket() + .CloseBracket() + .CloseBracket() + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondEq, 5) + .Or() + .OpenBracket() + .Where(kFieldNameGenre, CondEq, 4) + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .CloseBracket() + .Not() + .Where(kFieldNameYear, CondRange, {2001, 2010}) + .OpenBracket() + .Where(kFieldNameRate, CondRange, + {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) + .Or() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Not() + .OpenBracket() + .OpenBracket() + .OpenBracket() + .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) + .Or() + .Where(kFieldNameId, CondEq, rand() % 5000) + .Where(kFieldNameTemp, CondEq, "") + .CloseBracket() + .Or() + .OpenBracket() + .Where(kFieldNameTemp, CondEq, "") + .Not() + .OpenBracket() + .Where(kFieldNameIsDeleted, CondEq, true) + .Or() + .Where(kFieldNameYear, CondGt, 2001) + .CloseBracket() + .CloseBracket() + .CloseBracket() + .CloseBracket() + .CloseBracket() + .Sort(sortIdx, sortOrder) + .Distinct(distinct)); + ExecuteAndVerify( + Query(default_namespace) + .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210).Limit(rand() % 100)) + .OpenBracket() + .Not() + .On(kFieldNameYear, randCond(), kFieldNameYear) + .Or() + .On(kFieldNameName, CondEq, kFieldNameName) + .Or() + .On(kFieldNameAge, randCond(), kFieldNameAge) + .CloseBracket() + .Distinct(distinct)); + + for (CondType cond : {CondEq, CondSet, CondLt, CondLe, CondGt, CondGe, CondRange}) { + const auto argsCount = minMaxArgs(cond, 20); + if (argsCount.min <= 1 && argsCount.max >= 1) { + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameUuid, cond, randUuid()) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameUuid, cond, randStrUuid()) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameUuidArr, cond, randUuid()) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameUuidArr, cond, randStrUuid()) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + } + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameUuid, cond, randHeterogeneousUuidArray(argsCount.min, argsCount.max)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameUuidArr, cond, randHeterogeneousUuidArray(argsCount.min, argsCount.max)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + std::vector compositeKeyValues; + VariantArray hetUuidArray = randHeterogeneousUuidArray(argsCount.min, argsCount.max); + compositeKeyValues.reserve(hetUuidArray.size()); + std::transform(std::make_move_iterator(hetUuidArray.begin()), std::make_move_iterator(hetUuidArray.end()), + std::back_inserter(compositeKeyValues), + [this](Variant&& uuid) { return VariantArray::Create(std::move(uuid), RandString()); }); + ExecuteAndVerify(Query(default_namespace) + .WhereComposite(kCompositeFieldUuidName, cond, compositeKeyValues) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + } + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameUuid, CondRange, randHeterogeneousUuidArray(2, 2)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameUuidArr, CondRange, randHeterogeneousUuidArray(2, 2)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify( + Query(default_namespace) + .WhereComposite(kCompositeFieldUuidName, CondRange, + {VariantArray::Create(nilUuid(), RandString()), VariantArray::Create(randUuid(), RandString())}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(Query(default_namespace).Where(kFieldNameId, CondEq, 10), CondAny, {}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Not() + .Where(Query(default_namespace), CondEmpty, {}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameId, CondLt, Query(default_namespace).Aggregate(AggAvg, {kFieldNameId})) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(kFieldNameGenre, CondSet, + Query(joinNs).Select({kFieldNameGenre}).Where(kFieldNameId, CondSet, {10, 20, 30, 40})) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify( + Query(default_namespace) + .Where(Query(joinNs).Select({kFieldNameGenre}).Where(kFieldNameId, CondGt, 10), CondSet, {10, 20, 30, 40}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(Query(joinNs).Select({kFieldNameGenre}).Where(kFieldNameId, CondGt, 10).Offset(1), CondSet, + {10, 20, 30, 40}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify( + Query(default_namespace) + .Where(Query(joinNs).Where(kFieldNameId, CondGt, 10).Aggregate(AggMax, {kFieldNameGenre}), CondRange, {48, 50}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(Query(joinNs).Where(kFieldNameId, CondGt, 10).ReqTotal(), CondGt, {50}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify( + Query(default_namespace) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondEq, 5) + .Not() + .Where(Query(default_namespace).Where(kFieldNameGenre, CondEq, 5), CondAny, {}) + .Or() + .Where(kFieldNameGenre, CondSet, + Query(joinNs).Select({kFieldNameGenre}).Where(kFieldNameId, CondSet, {10, 20, 30, 40})) + .Not() + .OpenBracket() + .Where(kFieldNameYear, CondRange, {2001, 2020}) + .Or() + .Where(kFieldNameName, CondLike, RandLikePattern()) + .Or() + .Where(Query(joinNs).Where(kFieldNameYear, CondEq, 2000 + rand() % 210), CondEmpty, {}) + .CloseBracket() + .Or() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .OpenBracket() + .Where(kFieldNameNumeric, CondLt, std::to_string(600)) + .Not() + .OpenBracket() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Where(kFieldNameGenre, CondLt, 6) + .Or() + .Where(kFieldNameId, CondLt, Query(default_namespace).Aggregate(AggAvg, {kFieldNameId})) + .CloseBracket() + .Not() + .Where(Query(joinNs).Where(kFieldNameId, CondGt, 10).Aggregate(AggMax, {kFieldNameGenre}), CondRange, {48, 50}) + .Or() + .Where(kFieldNameYear, CondEq, 10) + .CloseBracket()); + + ExecuteAndVerify(Query(default_namespace) + .Where(kCompositeFieldIdTemp, CondEq, + Query(default_namespace).Select({kCompositeFieldIdTemp}).Where(kFieldNameId, CondGt, 10)) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify( + Query(default_namespace) + .Where(Query(default_namespace).Select({kCompositeFieldUuidName}).Where(kFieldNameId, CondGt, 10), CondRange, + {VariantArray::Create(nilUuid(), RandString()), VariantArray::Create(randUuid(), RandString())}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(Query(default_namespace) + .Select({kCompositeFieldAgeGenre}) + .Where(kFieldNameId, CondGt, 10) + .Sort(kCompositeFieldAgeGenre, false) + .Limit(10), + CondLe, {Variant(VariantArray::Create(rand() % 50, rand() % 50))}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(Query(default_namespace).Where(kFieldNameId, CondGt, 10).ReqTotal(), CondGe, {10}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + + ExecuteAndVerify(Query(default_namespace) + .Where(Query(default_namespace).Where(kFieldNameId, CondGt, 10).CachedTotal(), CondGe, {10}) + .Distinct(distinct.c_str()) + .Sort(sortIdx, sortOrder)); + } + } + } + } catch (const reindexer::Error& err) { + ASSERT_TRUE(false) << err.what(); + } catch (const std::exception& err) { + ASSERT_TRUE(false) << err.what(); + } catch (...) { + ASSERT_TRUE(false); + } +} diff --git a/cpp_src/gtests/tests/fixtures/queries_api.h b/cpp_src/gtests/tests/fixtures/queries_api.h index ed95e3a38..a1d79cc76 100644 --- a/cpp_src/gtests/tests/fixtures/queries_api.h +++ b/cpp_src/gtests/tests/fixtures/queries_api.h @@ -210,46 +210,59 @@ class QueriesApi : public ReindexerApi, public QueriesVerifier { void initUUIDNs(); void FillUUIDNs(); void CheckUUIDQueries(); - - template - void ExecuteAndVerify(const Query& query, T... args) { + void CheckStandartQueries(); + void CheckDslQueries(); + void checkDslQuery(std::string_view dsl, Query&& checkQuery); + void CheckSqlQueries(); + void checkSqlQuery(std::string_view sql, Query&& checkQuery); + + template + void ExecuteAndVerify(Q&& query, Args&&... args) { reindexer::QueryResults qr; - const_cast(query).Explain(); + query.Explain(); Error err = rt.reindexer->Select(query, qr); - ASSERT_TRUE(err.ok()) << err.what(); - Verify(qr, query, *rt.reindexer); - Verify(qr, args...); + ASSERT_TRUE(err.ok()) << err.what() << '\n' << query.GetSQL(); + if constexpr (std::is_rvalue_reference_v) { + Verify(qr, std::move(query), *rt.reindexer); + } else { + Verify(qr, reindexer::Query(query), *rt.reindexer); + } + Verify(qr, std::forward(args)...); } - void ExecuteAndVerifyWithSql(const Query& query) { + template + void ExecuteAndVerifyWithSql(Q&& query) { ExecuteAndVerify(query); - Query queryFromSql; - queryFromSql.FromSQL(query.GetSQL()); - ExecuteAndVerify(queryFromSql); + Query queryFromSql = Query::FromSQL(query.GetSQL()); + ExecuteAndVerify(std::move(queryFromSql)); } - template - void ExecuteAndVerify(const Query& query, QueryResults& qr, T... args) { - const_cast(query).Explain(); + template + void ExecuteAndVerify(Q&& query, QueryResults& qr, Args&&... args) { + query.Explain(); Error err = rt.reindexer->Select(query, qr); ASSERT_TRUE(err.ok()) << err.what(); - Verify(qr, query, *rt.reindexer); - Verify(qr, args...); + if constexpr (std::is_rvalue_reference_v) { + Verify(qr, std::move(query), *rt.reindexer); + } else { + Verify(qr, reindexer::Query(query), *rt.reindexer); + } + Verify(qr, std::forward(args)...); } - void ExecuteAndVerifyWithSql(const Query& query, QueryResults& qr) { + template + void ExecuteAndVerifyWithSql(Q&& query, QueryResults& qr) { ExecuteAndVerify(query, qr); - Query queryFromSql; - queryFromSql.FromSQL(query.GetSQL()); + Query queryFromSql = Query::FromSQL(query.GetSQL()); qr.Clear(); - ExecuteAndVerify(queryFromSql, qr); + ExecuteAndVerify(std::move(queryFromSql), qr); } void Verify(const reindexer::QueryResults&) const noexcept {} - template + template void Verify(const reindexer::QueryResults& qr, const char* fieldName, const std::vector& expectedValues, - T... args) { + Args&&... args) { reindexer::WrSerializer ser; if (qr.Count() != expectedValues.size()) { ser << "Sizes different: expected size " << expectedValues.size() << ", obtained size " << qr.Count() << '\n'; @@ -281,7 +294,7 @@ class QueriesApi : public ReindexerApi, public QueriesVerifier { } FAIL() << ser.Slice() << std::endl; } - Verify(qr, args...); + Verify(qr, std::forward(args)...); } using QueriesVerifier::Verify; @@ -744,852 +757,6 @@ class QueriesApi : public ReindexerApi, public QueriesVerifier { } } - void CheckStandartQueries() { - try { - using namespace std::string_literals; - static const std::vector sortIdxs = { - "", - kFieldNameName, - kFieldNameYear, - kFieldNameRate, - kFieldNameBtreeIdsets, - std::string{"-2.5 * "} + kFieldNameRate + " / (" + kFieldNameYear + " + " + kFieldNameId + ')'}; - static const std::vector distincts = {"", kFieldNameYear, kFieldNameRate}; - static const std::vector sortOrders = {true, false}; - - for (const bool sortOrder : sortOrders) { - for (const auto& sortIdx : sortIdxs) { - for (const std::string& distinct : distincts) { - const int randomAge = rand() % 50; - const int randomGenre = rand() % 50; - const int randomGenreUpper = rand() % 100; - const int randomGenreLower = rand() % 100; - - ExecuteAndVerify(Query(default_namespace).Distinct(distinct.c_str()).Sort(sortIdx, sortOrder).Limit(1)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondEq, randomGenre) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondEq, std::to_string(randomGenre)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameName, CondEq, RandString()) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameRate, CondEq, (rand() % 100) / 10.0) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameRate, CondEq, std::to_string((rand() % 100) / 10.0)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondGt, randomGenre) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameName, CondGt, RandString()) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameRate, CondGt, (rand() % 100) / 10.0) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondLt, randomGenre) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondLt, std::to_string(randomGenre)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameName, CondLt, RandString()) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameRate, CondLt, (rand() % 100) / 10.0) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameRate, CondLt, std::to_string((rand() % 100) / 10.0)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameBtreeIdsets, CondLt, static_cast(rand() % 10000)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameBtreeIdsets, CondGt, static_cast(rand() % 10000)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameBtreeIdsets, CondEq, static_cast(rand() % 10000)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondRange, {randomGenreLower, randomGenreUpper}) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameName, CondRange, {RandString(), RandString()}) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameName, CondLike, RandLikePattern()) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameRate, CondRange, - {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNamePackages, CondSet, RandIntVector(10, 10000, 50)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNamePackages, CondAllSet, RandIntVector(2, 10000, 50)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNamePackages, CondAllSet, 10000 + rand() % 50) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - // check substituteCompositIndexes - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameAge, CondEq, randomAge) - .Where(kFieldNameGenre, CondEq, randomGenre) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) - .Where(kFieldNameGenre, CondEq, randomGenre) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameAge, CondAllSet, RandIntVector(1, 0, 50)) - .Where(kFieldNameGenre, CondEq, randomGenre) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) - .Where(kFieldNameGenre, CondSet, RandIntVector(10, 0, 50)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 20)) - .Where(kFieldNameGenre, CondSet, RandIntVector(10, 0, 50)) - .Where(kFieldNameAge, CondSet, RandIntVector(10, 30, 50)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 20)) - .Where(kFieldNameGenre, CondEq, randomGenre) - .Where(kFieldNameAge, CondSet, RandIntVector(10, 30, 50)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - // end of check substituteCompositIndexes - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNamePackages, CondEmpty, {}) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameName, CondRange, {RandString(), RandString()}) - .Distinct(distinct.c_str()) - .Sort(kFieldNameYear, true) - .Sort(kFieldNameName, false) - .Sort(kFieldNameLocation, true)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameName, CondRange, {RandString(), RandString()}) - .Distinct(distinct.c_str()) - .Sort(kFieldNameGenre, true) - .Sort(kFieldNameActor, false) - .Sort(kFieldNameRate, true) - .Sort(kFieldNameLocation, false)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameName, CondLike, RandLikePattern()) - .Distinct(distinct.c_str()) - .Sort(kFieldNameGenre, true) - .Sort(kFieldNameActor, false) - .Sort(kFieldNameRate, true) - .Sort(kFieldNameLocation, false)); - - ExecuteAndVerify(Query(default_namespace).Sort(kFieldNameGenre, true, {10, 20, 30})); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNamePackages, CondAny, {}) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameIsDeleted, CondEq, 1) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Where(kFieldNameGenre, CondEq, 5) - .Where(kFieldNameAge, CondEq, 3) - .Where(kFieldNameYear, CondGe, 2010) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Debug(LogTrace)); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameGenre, CondEq, 5) - .Where(kFieldNameAge, CondEq, 3) - .Where(kFieldNameGenre, CondEq, 5) - .Where(kFieldNameAge, CondEq, 3) - .OpenBracket() - .Where(kFieldNameYear, CondGe, 2010) - .CloseBracket() - .Or() - .Where(kFieldNameYear, CondGe, 2010)); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameYear, CondGt, 2002) - .Where(kFieldNameGenre, CondEq, 4) - .Where(kFieldNameAge, CondEq, 3) - .Where(kFieldNameIsDeleted, CondEq, 3) - .Or() - .Where(kFieldNameYear, CondGt, 2001) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Debug(LogTrace)); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameAge, CondSet, {1, 2, 3, 4}) - .Where(kFieldNameId, CondEq, rand() % 5000) - .Where(kFieldNameTemp, CondEq, "") - .Where(kFieldNameIsDeleted, CondEq, 1) - .Or() - .Where(kFieldNameYear, CondGt, 2001) - .Debug(LogTrace)); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameGenre, CondSet, {5, 1, 7}) - .Where(kFieldNameYear, CondLt, 2010) - .Where(kFieldNameGenre, CondEq, 3) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Or() - .Where(kFieldNamePackages, CondEmpty, {}) - .Debug(LogTrace)); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameGenre, CondSet, {5, 1, 7}) - .Where(kFieldNameYear, CondLt, 2010) - .Or() - .Where(kFieldNamePackages, CondAny, {}) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Debug(LogTrace)); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameGenre, CondEq, 5) - .Or() - .Where(kFieldNameGenre, CondEq, 6) - .Where(kFieldNameYear, CondRange, {2001, 2020}) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50))); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameGenre, CondEq, 5) - .Or() - .Where(kFieldNameGenre, CondEq, 6) - .Not() - .Where(kFieldNameName, CondLike, RandLikePattern()) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50))); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameActor, CondEq, RandString())); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Not() - .Where(kFieldNameGenre, CondEq, 5) - .Where(kFieldNameYear, CondRange, {2001, 2020}) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50))); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameGenre, CondEq, 5) - .Not() - .Where(kFieldNameYear, CondRange, {2001, 2020}) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50))); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Not() - .Where(kFieldNameYear, CondEq, 10)); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(kFieldNameNumeric, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameNumeric, CondGt, std::to_string(5))); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(kFieldNameNumeric, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameNumeric, CondLt, std::to_string(600))); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameGenre, CondEq, 5) - .Or() - .OpenBracket() - .Where(kFieldNameGenre, CondLt, 6) - .Where(kFieldNameYear, CondRange, {2001, 2020}) - .CloseBracket() - .Not() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .OpenBracket() - .Where(kFieldNameNumeric, CondLt, std::to_string(600)) - .Or() - .OpenBracket() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Where(kFieldNameName, CondLike, RandLikePattern()) - .CloseBracket() - .Or() - .Where(kFieldNameYear, CondEq, 10) - .CloseBracket()); - - ExecuteAndVerify(Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameGenre, CondEq, 5) - .Not() - .OpenBracket() - .Where(kFieldNameYear, CondRange, {2001, 2020}) - .Or() - .Where(kFieldNameName, CondLike, RandLikePattern()) - .CloseBracket() - .Or() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .OpenBracket() - .Where(kFieldNameNumeric, CondLt, std::to_string(600)) - .Not() - .OpenBracket() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Where(kFieldNameGenre, CondLt, 6) - .CloseBracket() - .Or() - .Where(kFieldNameYear, CondEq, 10) - .CloseBracket()); - - ExecuteAndVerify( - Query(default_namespace) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder) - .Debug(LogTrace) - .Where(kFieldNameNumeric, CondRange, {std::to_string(rand() % 100), std::to_string(rand() % 100 + 500)})); - - ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameName, CondEq, "SSS")); - ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameYear, CondEq, 2002)); - ExecuteAndVerify(Query(testSimpleNs).Where(kFieldNameYear, CondEq, 2002).Not().Where(kFieldNameName, CondEq, 2002)); - ExecuteAndVerify( - Query(testSimpleNs).Where(kFieldNameName, CondEq, "SSS").Not().Where(kFieldNameYear, CondEq, 2002)); - ExecuteAndVerify( - Query(testSimpleNs).Where(kFieldNameName, CondEq, "SSS").Not().Where(kFieldNameYear, CondEq, 1989)); - ExecuteAndVerify( - Query(testSimpleNs).Where(kFieldNameYear, CondEq, 2002).Not().Where(kFieldNameName, CondEq, "MMM")); - - ExecuteAndVerify(Query(default_namespace) - .ReqTotal() - .Distinct(distinct) - .Sort(sortIdx, sortOrder) - .WhereComposite(kCompositeFieldAgeGenre, CondLe, {{Variant(27), Variant(10000)}})); - - ExecuteAndVerify(Query(default_namespace) - .ReqTotal() - .Distinct(distinct) - .Sort(kFieldNameAge + " + "s + kFieldNameId, sortOrder) - .Sort(kFieldNameRate + " * "s + kFieldNameGenre, sortOrder)); - - ExecuteAndVerify( - Query(default_namespace) - .ReqTotal() - .Distinct(distinct) - .Sort(sortIdx, sortOrder) - .WhereComposite(kCompositeFieldAgeGenre, CondEq, {{Variant(rand() % 10), Variant(rand() % 50)}})); - - ExecuteAndVerify(Query(default_namespace) - .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, Query(joinNs)) - .Distinct(distinct) - .Sort(joinNs + '.' + kFieldNameId, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, Query(joinNs)) - .Distinct(distinct) - .Sort(joinNs + '.' + kFieldNameName, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, Query(joinNs)) - .Distinct(distinct) - .Sort(joinNs + '.' + kFieldNameId + " * " + joinNs + '.' + kFieldNameGenre + - (sortIdx.empty() || (sortIdx == kFieldNameName) ? "" : (" + " + sortIdx)), - sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, - Query(joinNs) - .Where(kFieldNameId, CondSet, RandIntVector(20, 0, 100)) - .Sort(kFieldNameId + " + "s + kFieldNameYear, sortOrder)) - .Distinct(distinct)); - - ExecuteAndVerify(Query(default_namespace) - .InnerJoin(kFieldNameYear, kFieldNameYear, CondEq, - Query(joinNs) - .Where(kFieldNameYear, CondGe, 1925) - .Sort(kFieldNameId + " + "s + kFieldNameYear, sortOrder)) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .InnerJoin(kFieldNameYear, kFieldNameYear, randCond(), - Query(joinNs).Where(kFieldNameYear, CondGe, 2000 + rand() % 210)) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .InnerJoin(kFieldNameYear, kFieldNameYear, randCond(), - Query(joinNs).Where(kFieldNameYear, CondLe, 2000 + rand() % 210).Limit(rand() % 10)) - .Distinct(distinct)); - ExecuteAndVerify( - Query(default_namespace) - .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210) /*.Offset(rand() % 10)*/) - .On(kFieldNameYear, randCond(), kFieldNameYear) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameYearSparse, CondEq, std::to_string(2000 + rand() % 60)) - .Distinct(distinct)); - ExecuteAndVerify( - Query(default_namespace) - .InnerJoin(kFieldNameYear, kFieldNameYear, randCond(), - Query(joinNs).Where(kFieldNameYear, CondLt, 2000 + rand() % 210).Sort(kFieldNameName, sortOrder)) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210)) - .OpenBracket() - .On(kFieldNameYear, randCond(), kFieldNameYear) - .Or() - .On(kFieldNameName, CondEq, kFieldNameName) - .CloseBracket() - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210)) - .OpenBracket() - .On(kFieldNameYear, randCond(), kFieldNameYear) - .Or() - .On(kFieldNameName, CondEq, kFieldNameName) - .On(kFieldNameAge, randCond(), kFieldNameAge) - .Not() - .On(kFieldNameYear, randCond(), kFieldNameYear) - .CloseBracket() - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210)) - .OpenBracket() - .On(kFieldNameYearSparse, CondLe, kFieldNameYearSparse) - .Or() - .On(kFieldNameName, CondEq, kFieldNameName) - .Or() - .On(kFieldNameAge, randCond(), kFieldNameAge) - .Not() - .On(kFieldNameYear, randCond(), kFieldNameYear) - .CloseBracket() - .Distinct(distinct)); - ExecuteAndVerify( - Query(default_namespace) - .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210).Limit(rand() % 100)) - .OpenBracket() - .On(kFieldNameYear, randCond(), kFieldNameYear) - .Or() - .On(kFieldNameName, CondEq, kFieldNameName) - .Or() - .On(kFieldNameAge, randCond(), kFieldNameAge) - .CloseBracket() - .Or() - .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondLt, 2000 + rand() % 210).Limit(rand() % 100)) - .OpenBracket() - .On(kFieldNameYear, randCond(), kFieldNameYear) - .Or() - .On(kFieldNameName, CondEq, kFieldNameName) - .Or() - .On(kFieldNameAge, randCond(), kFieldNameAge) - .CloseBracket() - .Join(OrInnerJoin, Query(joinNs).Where(kFieldNameYear, CondEq, 2000 + rand() % 210).Limit(rand() % 100)) - .OpenBracket() - .On(kFieldNameYear, randCond(), kFieldNameYear) - .Or() - .On(kFieldNameName, CondEq, kFieldNameName) - .Or() - .On(kFieldNameAge, randCond(), kFieldNameAge) - .CloseBracket() - .Or() - .Where(kFieldNameId, CondSet, RandIntVector(20, 0, 100)) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .WhereBetweenFields(kFieldNameGenre, CondEq, kFieldNameAge) - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .WhereBetweenFields(kFieldNameName, CondLike, kFieldNameActor) - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .WhereBetweenFields(kFieldNamePackages, CondGt, kFieldNameStartTime) - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify( - Query(compositeIndexesNs).WhereBetweenFields(kCompositeFieldPriceTitle, CondEq, kCompositeFieldPagesTitle)); - ExecuteAndVerify(Query(default_namespace) - .Not() - .Where(kFieldNameIsDeleted, CondEq, true) - .Or() - .Where(kFieldNameYear, CondGt, 2001) - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondEq, 5) - .Or() - .OpenBracket() - .Where(kFieldNameGenre, CondEq, 4) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .CloseBracket() - .Not() - .Where(kFieldNameYear, CondRange, {2001, 2010}) - .OpenBracket() - .Where(kFieldNameRate, CondRange, - {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) - .Or() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Not() - .OpenBracket() - .OpenBracket() - .OpenBracket() - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) - .Or() - .Where(kFieldNameId, CondEq, rand() % 5000) - .Where(kFieldNameTemp, CondEq, "") - .CloseBracket() - .Or() - .OpenBracket() - .Where(kFieldNameTemp, CondEq, "") - .Not() - .Where(kFieldNameIsDeleted, CondEq, true) - .Or() - .Where(kFieldNameYear, CondGt, 2001) - .CloseBracket() - .CloseBracket() - .CloseBracket() - .CloseBracket() - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondEq, 5) - .Or() - .OpenBracket() - .Where(kFieldNameGenre, CondEq, 4) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .CloseBracket() - .Not() - .Where(kFieldNameYear, CondRange, {2001, 2010}) - .OpenBracket() - .Where(kFieldNameRate, CondRange, - {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) - .Or() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Not() - .OpenBracket() - .OpenBracket() - .OpenBracket() - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) - .Or() - .Where(kFieldNameId, CondEq, rand() % 5000) - .Where(kFieldNameTemp, CondEq, "") - .CloseBracket() - .Or() - .OpenBracket() - .Where(kFieldNameTemp, CondEq, "") - .Not() - .OpenBracket() - .Where(kFieldNameIsDeleted, CondEq, true) - .CloseBracket() - .Or() - .Where(kFieldNameYear, CondGt, 2001) - .CloseBracket() - .CloseBracket() - .CloseBracket() - .CloseBracket() - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondEq, 5) - .Or() - .OpenBracket() - .Where(kFieldNameGenre, CondEq, 4) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .CloseBracket() - .Not() - .Where(kFieldNameYear, CondRange, {2001, 2010}) - .OpenBracket() - .Where(kFieldNameRate, CondRange, - {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) - .Or() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Not() - .OpenBracket() - .OpenBracket() - .OpenBracket() - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) - .Or() - .Where(kFieldNameId, CondEq, rand() % 5000) - .Where(kFieldNameTemp, CondEq, "") - .CloseBracket() - .Or() - .OpenBracket() - .Where(kFieldNameTemp, CondEq, "") - .OpenBracket() - .Not() - .Where(kFieldNameIsDeleted, CondEq, true) - .CloseBracket() - .Or() - .Where(kFieldNameYear, CondGt, 2001) - .CloseBracket() - .CloseBracket() - .CloseBracket() - .CloseBracket() - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondEq, 5) - .Or() - .OpenBracket() - .Where(kFieldNameGenre, CondEq, 4) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .CloseBracket() - .Not() - .Where(kFieldNameYear, CondRange, {2001, 2010}) - .OpenBracket() - .Where(kFieldNameRate, CondRange, - {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) - .Or() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Not() - .OpenBracket() - .OpenBracket() - .OpenBracket() - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) - .Or() - .Where(kFieldNameId, CondEq, rand() % 5000) - .Where(kFieldNameTemp, CondEq, "") - .CloseBracket() - .Or() - .OpenBracket() - .Where(kFieldNameTemp, CondEq, "") - .OpenBracket() - .Not() - .Where(kFieldNameIsDeleted, CondEq, true) - .Or() - .Where(kFieldNameYear, CondGt, 2001) - .CloseBracket() - .CloseBracket() - .CloseBracket() - .CloseBracket() - .CloseBracket() - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameGenre, CondEq, 5) - .Or() - .OpenBracket() - .Where(kFieldNameGenre, CondEq, 4) - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .CloseBracket() - .Not() - .Where(kFieldNameYear, CondRange, {2001, 2010}) - .OpenBracket() - .Where(kFieldNameRate, CondRange, - {static_cast(rand() % 100) / 10, static_cast(rand() % 100) / 10}) - .Or() - .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) - .Not() - .OpenBracket() - .OpenBracket() - .OpenBracket() - .Where(kFieldNameAge, CondSet, RandIntVector(10, 0, 50)) - .Or() - .Where(kFieldNameId, CondEq, rand() % 5000) - .Where(kFieldNameTemp, CondEq, "") - .CloseBracket() - .Or() - .OpenBracket() - .Where(kFieldNameTemp, CondEq, "") - .Not() - .OpenBracket() - .Where(kFieldNameIsDeleted, CondEq, true) - .Or() - .Where(kFieldNameYear, CondGt, 2001) - .CloseBracket() - .CloseBracket() - .CloseBracket() - .CloseBracket() - .CloseBracket() - .Sort(sortIdx, sortOrder) - .Distinct(distinct)); - ExecuteAndVerify( - Query(default_namespace) - .Join(InnerJoin, Query(joinNs).Where(kFieldNameYear, CondGt, 2000 + rand() % 210).Limit(rand() % 100)) - .OpenBracket() - .Not() - .On(kFieldNameYear, randCond(), kFieldNameYear) - .Or() - .On(kFieldNameName, CondEq, kFieldNameName) - .Or() - .On(kFieldNameAge, randCond(), kFieldNameAge) - .CloseBracket() - .Distinct(distinct)); - - for (CondType cond : {CondEq, CondSet, CondLt, CondLe, CondGt, CondGe, CondRange}) { - const auto argsCount = minMaxArgs(cond, 20); - if (argsCount.min <= 1 && argsCount.max >= 1) { - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameUuid, cond, randUuid()) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameUuid, cond, randStrUuid()) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameUuidArr, cond, randUuid()) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameUuidArr, cond, randStrUuid()) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - } - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameUuid, cond, randHeterogeneousUuidArray(argsCount.min, argsCount.max)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameUuidArr, cond, randHeterogeneousUuidArray(argsCount.min, argsCount.max)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - std::vector compositeKeyValues; - VariantArray hetUuidArray = randHeterogeneousUuidArray(argsCount.min, argsCount.max); - compositeKeyValues.reserve(hetUuidArray.size()); - std::transform(std::make_move_iterator(hetUuidArray.begin()), std::make_move_iterator(hetUuidArray.end()), - std::back_inserter(compositeKeyValues), - [this](Variant&& uuid) { return VariantArray::Create(std::move(uuid), RandString()); }); - ExecuteAndVerify(Query(default_namespace) - .WhereComposite(kCompositeFieldUuidName, cond, compositeKeyValues) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - } - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameUuid, CondRange, randHeterogeneousUuidArray(2, 2)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .Where(kFieldNameUuidArr, CondRange, randHeterogeneousUuidArray(2, 2)) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - - ExecuteAndVerify(Query(default_namespace) - .WhereComposite(kCompositeFieldUuidName, CondRange, - {VariantArray::Create(nilUuid(), RandString()), - VariantArray::Create(randUuid(), RandString())}) - .Distinct(distinct.c_str()) - .Sort(sortIdx, sortOrder)); - } - } - } - } catch (const reindexer::Error& err) { - ASSERT_TRUE(false) << err.what(); - } catch (const std::exception& err) { - ASSERT_TRUE(false) << err.what(); - } catch (...) { - ASSERT_TRUE(false); - } - } static CondType randCond() noexcept { constexpr static CondType conds[]{CondEq, CondSet, CondLt, CondLe, CondGe, CondGt}; return conds[rand() % (sizeof(conds) / sizeof(*conds))]; @@ -1686,13 +853,14 @@ class QueriesApi : public ReindexerApi, public QueriesVerifier { constexpr size_t facetLimit = 10; constexpr size_t facetOffset = 10; - EXPECT_THROW(Query(default_namespace).Aggregate(AggAvg, {}), reindexer::Error); + Query q(default_namespace); + EXPECT_THROW(q.Aggregate(AggAvg, {}), reindexer::Error); - EXPECT_THROW(Query(default_namespace).Aggregate(AggAvg, {kFieldNameYear, kFieldNameName}), reindexer::Error); + EXPECT_THROW(q.Aggregate(AggAvg, {kFieldNameYear, kFieldNameName}), reindexer::Error); - EXPECT_THROW(Query(default_namespace).Aggregate(AggAvg, {kFieldNameYear}, {{kFieldNameYear, true}}), reindexer::Error); + EXPECT_THROW(q.Aggregate(AggAvg, {kFieldNameYear}, {{kFieldNameYear, true}}), reindexer::Error); - EXPECT_THROW(Query(default_namespace).Aggregate(AggAvg, {kFieldNameYear}, {}, 10), reindexer::Error); + EXPECT_THROW(q.Aggregate(AggAvg, {kFieldNameYear}, {}, 10), reindexer::Error); const Query wrongQuery1{Query(default_namespace).Aggregate(AggFacet, {kFieldNameYear}, {{kFieldNameName, true}})}; reindexer::QueryResults wrongQr1; @@ -1793,7 +961,7 @@ class QueriesApi : public ReindexerApi, public QueriesVerifier { checkFacet(testQr.aggregationResults[9].facets, multifieldFacet, "Multifield"); } - void CompareQueryResults(const std::string& serializedQuery, const QueryResults& lhs, const QueryResults& rhs) { + void CompareQueryResults(std::string_view serializedQuery, const QueryResults& lhs, const QueryResults& rhs) { EXPECT_EQ(lhs.Count(), rhs.Count()); if (lhs.Count() == rhs.Count()) { for (size_t i = 0; i < lhs.Count(); ++i) { @@ -1852,238 +1020,12 @@ class QueriesApi : public ReindexerApi, public QueriesVerifier { } } - void checkDslQuery(const std::string& dslQuery, const Query& checkQuery) { - Query parsedQuery; - Error err = parsedQuery.FromJSON(dslQuery); - ASSERT_TRUE(err.ok()) << "Query: " << dslQuery << "; err: " << err.what(); - - QueryResults dslQr; - err = rt.reindexer->Select(parsedQuery, dslQr); - ASSERT_TRUE(err.ok()) << "Query: " << dslQuery << "; err: " << err.what(); - - QueryResults checkQr; - err = rt.reindexer->Select(checkQuery, checkQr); - ASSERT_TRUE(err.ok()) << "Query: " << dslQuery << "; err: " << err.what(); - - CompareQueryResults(dslQuery, dslQr, checkQr); - Verify(checkQr, checkQuery, *rt.reindexer); - } - static std::string toString(double v) { std::ostringstream res; res.precision(std::numeric_limits::digits10 + 1); res << v; return res.str(); } - // Checks that DSL queries works and compares the result with the result of corresponding C++ query - void CheckDslQueries() { - using namespace std::string_literals; - using reindexer::randPoint; - using reindexer::randBinDouble; - // ---------- - reindexer::Point point{randPoint(10)}; - double distance = randBinDouble(0, 1); - std::string dslQuery = fmt::sprintf( - R"({"namespace":"%s","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"dwithin","field":"%s","value":[[%f, %f], %f]}],"merge_queries":[],"aggregations":[]})", - geomNs, kFieldNamePointLinearRTree, point.X(), point.Y(), distance); - const Query checkQuery1{Query(geomNs).DWithin(kFieldNamePointLinearRTree, point, distance)}; - checkDslQuery(dslQuery, checkQuery1); - - // ---------- - point = randPoint(10); - distance = randBinDouble(0, 1); - dslQuery = fmt::sprintf( - R"({"namespace":"%s","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"dwithin","field":"%s","value":[%f,[%f,%f]]}],"merge_queries":[],"aggregations":[]})", - geomNs, kFieldNamePointLinearRTree, distance, point.X(), point.Y()); - const Query checkQuery2{Query(geomNs).DWithin(kFieldNamePointLinearRTree, point, distance)}; - checkDslQuery(dslQuery, checkQuery2); - - // ---------- - dslQuery = fmt::sprintf( - R"({"namespace":"%s","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"gt","first_field":"%s","second_field":"%s"}],"merge_queries":[],"aggregations":[]})", - default_namespace, kFieldNameStartTime, kFieldNamePackages); - const Query checkQuery3{Query{default_namespace}.WhereBetweenFields(kFieldNameStartTime, CondGt, kFieldNamePackages)}; - checkDslQuery(dslQuery, checkQuery3); - - // ------- - dslQuery = fmt::sprintf( - R"({"namespace":"%s","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"SET","field":"%s","Value":["1", " 10 ", "100 ", " 1000"]}],"merge_queries":[],"aggregations":[]})", - default_namespace, kFieldNameId); - const Query checkQuery4{Query{default_namespace}.Where(kFieldNameId, CondSet, {1, 10, 100, 1000})}; - checkDslQuery(dslQuery, checkQuery4); - } - - void CheckSqlQueries() { - using namespace std::string_literals; - using reindexer::randPoint; - using reindexer::randBinDouble; - std::string sqlQuery = "SELECT ID, Year, Genre FROM test_namespace WHERE year > '2016' ORDER BY year DESC LIMIT 10000000"; - const Query checkQuery1{Query(default_namespace, 0, 10000000).Where(kFieldNameYear, CondGt, 2016).Sort(kFieldNameYear, true)}; - - QueryResults sqlQr1; - Error err = rt.reindexer->Select(sqlQuery, sqlQr1); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr1; - err = rt.reindexer->Select(checkQuery1, checkQr1); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr1, checkQr1); - Verify(checkQr1, checkQuery1, *rt.reindexer); - - sqlQuery = "SELECT ID, Year, Genre FROM test_namespace WHERE genre IN ('1',2,'3') ORDER BY year DESC LIMIT 10000000"; - const Query checkQuery2{ - Query(default_namespace, 0, 10000000).Where(kFieldNameGenre, CondSet, {1, 2, 3}).Sort(kFieldNameYear, true)}; - - QueryResults sqlQr2; - err = rt.reindexer->Select(sqlQuery, sqlQr2); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr2; - err = rt.reindexer->Select(checkQuery2, checkQr2); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr2, checkQr2); - Verify(checkQr2, checkQuery2, *rt.reindexer); - - const std::string likePattern = RandLikePattern(); - sqlQuery = "SELECT ID, Year, Genre FROM test_namespace WHERE name LIKE '" + likePattern + "' ORDER BY year DESC LIMIT 10000000"; - const Query checkQuery3{ - Query(default_namespace, 0, 10000000).Where(kFieldNameName, CondLike, likePattern).Sort(kFieldNameYear, true)}; - - QueryResults sqlQr3; - err = rt.reindexer->Select(sqlQuery, sqlQr3); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr3; - err = rt.reindexer->Select(checkQuery3, checkQr3); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr3, checkQr3); - Verify(checkQr3, checkQuery3, *rt.reindexer); - - sqlQuery = "SELECT FACET(ID, Year ORDER BY ID DESC ORDER BY Year ASC LIMIT 20 OFFSET 1) FROM test_namespace LIMIT 10000000"; - const Query checkQuery4{ - Query(default_namespace, 0, 10000000) - .Aggregate(AggFacet, {kFieldNameId, kFieldNameYear}, {{kFieldNameId, true}, {kFieldNameYear, false}}, 20, 1)}; - - QueryResults sqlQr4; - err = rt.reindexer->Select(sqlQuery, sqlQr4); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr4; - err = rt.reindexer->Select(checkQuery4, checkQr4); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr4, checkQr4); - Verify(checkQr4, checkQuery4, *rt.reindexer); - - sqlQuery = "SELECT ID FROM test_namespace WHERE name LIKE '" + likePattern + - "' AND (genre IN ('1', '2', '3') AND year > '2016' ) OR age IN ('1', '2', '3', '4') LIMIT 10000000"; - const Query checkQuery5{Query(default_namespace, 0, 10000000) - .Where(kFieldNameName, CondLike, likePattern) - .OpenBracket() - .Where(kFieldNameGenre, CondSet, {1, 2, 3}) - .Where(kFieldNameYear, CondGt, 2016) - .CloseBracket() - .Or() - .Where(kFieldNameAge, CondSet, {1, 2, 3, 4})}; - - QueryResults sqlQr5; - err = rt.reindexer->Select(sqlQuery, sqlQr5); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr5; - err = rt.reindexer->Select(checkQuery5, checkQr5); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr5, checkQr5); - Verify(checkQr5, checkQuery5, *rt.reindexer); - - sqlQuery = fmt::sprintf("SELECT ID FROM test_namespace ORDER BY '%s + %s * 5' DESC LIMIT 10000000", kFieldNameYear, kFieldNameId); - const Query checkQuery6{ - Query(default_namespace, 0, 10000000).Sort(kFieldNameYear + std::string(" + ") + kFieldNameId + " * 5", true)}; - - QueryResults sqlQr6; - err = rt.reindexer->Select(sqlQuery, sqlQr6); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr6; - err = rt.reindexer->Select(checkQuery6, checkQr6); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr6, checkQr6); - Verify(checkQr6, checkQuery6, *rt.reindexer); - - sqlQuery = fmt::sprintf("SELECT ID FROM test_namespace ORDER BY '%s + %s * 5' DESC ORDER BY '2 * %s / (1 + %s)' ASC LIMIT 10000000", - kFieldNameYear, kFieldNameId, kFieldNameGenre, kFieldNameIsDeleted); - const Query checkQuery7{Query(default_namespace, 0, 10000000) - .Sort(kFieldNameYear + std::string(" + ") + kFieldNameId + " * 5", true) - .Sort(std::string("2 * ") + kFieldNameGenre + " / (1 + " + kFieldNameIsDeleted + ')', false)}; - - QueryResults sqlQr7; - err = rt.reindexer->Select(sqlQuery, sqlQr7); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr7; - err = rt.reindexer->Select(checkQuery7, checkQr7); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr7, checkQr7); - Verify(checkQr7, checkQuery7, *rt.reindexer); - - // Checks that SQL queries with DWithin and sort by Distance work and compares the result with the result of corresponding C++ query - reindexer::Point point = randPoint(10); - double distance = randBinDouble(0, 1); - sqlQuery = fmt::sprintf("SELECT * FROM %s WHERE ST_DWithin(%s, %s, %s);", geomNs, kFieldNamePointNonIndex, pointToSQL(point), - toString(distance)); - const Query checkQuery8{Query(geomNs).DWithin(kFieldNamePointNonIndex, point, distance)}; - - QueryResults sqlQr8; - err = rt.reindexer->Select(sqlQuery, sqlQr8); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr8; - err = rt.reindexer->Select(checkQuery8, checkQr8); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr8, checkQr8); - Verify(checkQr8, checkQuery8, *rt.reindexer); - - point = randPoint(10); - distance = randBinDouble(0, 1); - sqlQuery = fmt::sprintf("SELECT * FROM %s WHERE ST_DWithin(%s, %s, %s) ORDER BY 'ST_Distance(%s, %s)';", geomNs, pointToSQL(point), - kFieldNamePointNonIndex, toString(distance), kFieldNamePointLinearRTree, pointToSQL(point, true)); - const Query checkQuery9{ - Query(geomNs) - .DWithin(kFieldNamePointNonIndex, point, distance) - .Sort(std::string("ST_Distance(") + kFieldNamePointLinearRTree + ", " + pointToSQL(point) + ')', false)}; - - QueryResults sqlQr9; - err = rt.reindexer->Select(sqlQuery, sqlQr9); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr9; - err = rt.reindexer->Select(checkQuery9, checkQr9); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr9, checkQr9); - Verify(checkQr9, checkQuery9, *rt.reindexer); - - sqlQuery = fmt::sprintf("SELECT * FROM %s WHERE %s >= %s;", default_namespace, kFieldNameGenre, kFieldNameRate); - const Query checkQuery10{Query(default_namespace).WhereBetweenFields(kFieldNameGenre, CondGe, kFieldNameRate)}; - - QueryResults sqlQr10; - err = rt.reindexer->Select(sqlQuery, sqlQr10); - ASSERT_TRUE(err.ok()) << err.what(); - - QueryResults checkQr10; - err = rt.reindexer->Select(checkQuery10, checkQr10); - ASSERT_TRUE(err.ok()) << err.what(); - - CompareQueryResults(sqlQuery, sqlQr10, checkQr10); - Verify(checkQr10, checkQuery10, *rt.reindexer); - } void CheckCompositeIndexesQueries() { int priceValue = 77777; diff --git a/cpp_src/gtests/tests/fixtures/queries_verifier.h b/cpp_src/gtests/tests/fixtures/queries_verifier.h index ed717fdca..6929958fc 100644 --- a/cpp_src/gtests/tests/fixtures/queries_verifier.h +++ b/cpp_src/gtests/tests/fixtures/queries_verifier.h @@ -28,7 +28,8 @@ class QueriesVerifier : public virtual ::testing::Test { }; using IndexesData = std::unordered_map>; - void Verify(const reindexer::QueryResults& qr, const reindexer::Query& query, reindexer::Reindexer& rx) { + void Verify(const reindexer::QueryResults& qr, reindexer::Query&& q, reindexer::Reindexer& rx) { + auto query = std::move(q); std::unordered_set, PkHash> pks; std::unordered_map> distincts; QueryWatcher watcher{query}; @@ -36,11 +37,79 @@ class QueriesVerifier : public virtual ::testing::Test { reindexer::VariantArray lastSortedColumnValues; lastSortedColumnValues.resize(query.sortingEntries_.size()); + for (size_t i = 0; i < query.Entries().Size(); ++i) { + query.Entries().InvokeAppropriate( + i, + reindexer::Skip{}, + [&](const reindexer::SubQueryEntry& sqe) { + auto subQuery = query.GetSubQuery(sqe.QueryIndex()); + if (sqe.Condition() == CondAny || sqe.Condition() == CondEmpty) { + subQuery.Limit(1); + } + reindexer::QueryResults qr; + const auto err = rx.Select(subQuery, qr); + ASSERT_TRUE(err.ok()) << err.what(); + bool res = false; + if (sqe.Condition() == CondAny || sqe.Condition() == CondEmpty) { + res = ((qr.Count() != 0) == (sqe.Condition() == CondAny)); + } else if (qr.GetAggregationResults().empty()) { + assert(!subQuery.SelectFilters().empty()); + reindexer::QueryEntry qe{subQuery.SelectFilters()[0], sqe.Condition(), reindexer::VariantArray(sqe.Values())}; + const auto& indexesFields = indexesFields_[subQuery.NsName()]; + for (auto it : qr) { + ASSERT_TRUE(it.Status().ok()) << it.Status().what(); + if (checkCondition(it.GetItem(), qe, indexesFields)) { + res = true; + break; + } + } + } else { + const auto aggRes = qr.GetAggregationResults()[0].GetValue(); + if (aggRes) { + res = compareValue(reindexer::Variant(*aggRes), sqe.Condition(), sqe.Values(), CollateOpts(), + reindexer::KeyValueType::Double{}); + } + } + if (res) { + query.SetEntry(i); + } else { + query.SetEntry(i); + } + }, + [&](const reindexer::SubQueryFieldEntry& sqe) { + auto& subQuery = query.GetSubQuery(sqe.QueryIndex()); + reindexer::QueryResults qr; + const auto err = rx.Select(subQuery, qr); + ASSERT_TRUE(err.ok()) << err.what(); + reindexer::VariantArray values; + if (qr.GetAggregationResults().empty()) { + ASSERT_FALSE(subQuery.SelectFilters().empty()); + const auto& indexesFields = indexesFields_[subQuery.NsName()]; + if (isIndexComposite(subQuery.SelectFilters()[0], indexesFields)) { + const auto fields = getCompositeFields(subQuery.SelectFilters()[0], indexesFields); + for (auto it : qr) { + ASSERT_TRUE(it.Status().ok()) << it.Status().what(); + values.emplace_back(getValues(it.GetItem(), fields)); + } + } else { + for (auto it : qr) { + ASSERT_TRUE(it.Status().ok()) << it.Status().what(); + values.emplace_back(it.GetItem()[subQuery.SelectFilters()[0]]); + } + } + } else { + ASSERT_TRUE(qr.GetAggregationResults()[0].GetValue().has_value()); + values.emplace_back(*qr.GetAggregationResults()[0].GetValue()); + } + query.SetEntry(i, sqe.FieldName(), sqe.Condition(), std::move(values)); + }); + } auto joinedSelectors = getJoinedSelectors(query); for (auto& js : joinedSelectors) { const reindexer::Error err = rx.Select(js.JoinQuery(), js.QueryResults()); ASSERT_TRUE(err.ok()) << err.what(); - Verify(js.QueryResults(), js.JoinQuery(), rx); + Verify(js.QueryResults(), reindexer::Query(static_cast(js.JoinQuery())), rx); } const auto& indexesFields = indexesFields_[query.NsName()]; for (size_t i = 0; i < qr.Count(); ++i) { @@ -62,7 +131,8 @@ class QueriesVerifier : public virtual ::testing::Test { << "explain: " << qr.GetExplainResults(); } - bool conditionsSatisfied = checkConditions(itemr, query.entries.cbegin(), query.entries.cend(), joinedSelectors, indexesFields); + bool conditionsSatisfied = + checkConditions(itemr, query.Entries().cbegin(), query.Entries().cend(), joinedSelectors, indexesFields); if (!conditionsSatisfied) { std::stringstream ss; ss << "Item doesn't match conditions: " << itemr.GetJSON() << std::endl; @@ -79,7 +149,7 @@ class QueriesVerifier : public virtual ::testing::Test { ss << "explain: " << qr.GetExplainResults(); EXPECT_TRUE(conditionsSatisfied) << ss.str(); TEST_COUT << query.GetSQL() << std::endl; - printFailedQueryEntries(query.entries, joinedSelectors); + printFailedQueryEntries(query.Entries(), joinedSelectors, query.GetSubQueries()); } EXPECT_TRUE(checkDistincts(itemr, query, distincts, indexesFields)) << "Distinction check failed"; @@ -154,7 +224,7 @@ class QueriesVerifier : public virtual ::testing::Test { for (auto& insertedItem : insertedItems_[query.NsName()]) { if (pks.find(insertedItem.first) != pks.end()) continue; bool conditionsSatisfied = - checkConditions(insertedItem.second, query.entries.cbegin(), query.entries.cend(), joinedSelectors, indexesFields); + checkConditions(insertedItem.second, query.Entries().cbegin(), query.Entries().cend(), joinedSelectors, indexesFields); EXPECT_FALSE(conditionsSatisfied) << "Item match conditions (found " << qr.Count() << " items), but not found: " << insertedItem.second.GetJSON() << std::endl @@ -163,7 +233,7 @@ class QueriesVerifier : public virtual ::testing::Test { } auto aggResults = qr.GetAggregationResults(); - if (query.CalcTotal() != ModeNoTotal) { + if (query.HasCalcTotal()) { // calcTotal from version 3.0.2 also return total count in aggregations, so we have remove it from here for // clean compare aggresults with aggregations aggResults.pop_back(); @@ -241,6 +311,8 @@ class QueriesVerifier : public virtual ::testing::Test { if (op != OpOr && !result) return false; bool skip = false; bool const iterationResult = it->InvokeAppropriate( + [](const reindexer::SubQueryEntry&) -> bool { assertrx(0); }, + [](const reindexer::SubQueryFieldEntry&) -> bool { assertrx(0); }, [&](const reindexer::QueryEntriesBracket&) { if (op == OpOr && result && !containsJoins(it.cbegin(), it.cend())) { skip = true; @@ -272,7 +344,7 @@ class QueriesVerifier : public virtual ::testing::Test { } return checkCondition(item, qe, indexesFields); }, - [](const reindexer::AlwaysFalse&) { return false; }); + [](const reindexer::AlwaysFalse&) noexcept { return false; }, [](const reindexer::AlwaysTrue&) noexcept { return true; }); if (skip) continue; switch (op) { case OpNot: @@ -304,8 +376,8 @@ class QueriesVerifier : public virtual ::testing::Test { const IndexesData& indexesFields) { bool result = true; // check only on root level - for (auto it = qr.entries.cbegin(); it != qr.entries.cend(); ++it) { - if (!it->HoldsOrReferTo()) continue; + for (auto it = qr.Entries().cbegin(); it != qr.Entries().cend(); ++it) { + if (!it->Is()) continue; const reindexer::QueryEntry& qentry = it->Value(); if (!qentry.Distinct()) continue; @@ -413,8 +485,9 @@ class QueriesVerifier : public virtual ::testing::Test { case CondLike: case CondDWithin: for (const reindexer::Variant& fieldValue : fieldValues) { - if (compareValue(fieldValue, qentry.Condition(), qentry.Values(), collate, fieldType)) + if (compareValue(fieldValue, qentry.Condition(), qentry.Values(), collate, fieldType)) { return true; + } } } } @@ -787,9 +860,14 @@ class QueriesVerifier : public virtual ::testing::Test { static bool containsJoins(reindexer::QueryEntries::const_iterator it, reindexer::QueryEntries::const_iterator end) noexcept { for (; it != end; ++it) { if (it->InvokeAppropriate( - [&it](const reindexer::QueryEntriesBracket&) { return containsJoins(it.cbegin(), it.cend()); }, - [](const reindexer::JoinQueryEntry&) { return true; }, [](const reindexer::QueryEntry&) { return false; }, - [](const reindexer::BetweenFieldsQueryEntry&) { return false; }, [](const reindexer::AlwaysFalse&) { return false; })) { + [&it](const reindexer::QueryEntriesBracket&) noexcept { return containsJoins(it.cbegin(), it.cend()); }, + [](const reindexer::JoinQueryEntry&) noexcept { return true; }, + [](const reindexer::QueryEntry&) noexcept { return false; }, + [](const reindexer::BetweenFieldsQueryEntry&) noexcept { return false; }, + [](const reindexer::AlwaysFalse&) noexcept { return false; }, + [](const reindexer::AlwaysTrue&) noexcept { return true; }, + [](const reindexer::SubQueryEntry&) noexcept { return false; }, + [](const reindexer::SubQueryFieldEntry&) noexcept { return false; })) { return true; } } @@ -798,8 +876,8 @@ class QueriesVerifier : public virtual ::testing::Test { static std::vector getJoinedSelectors(const reindexer::Query& query) { std::vector result; - result.reserve(query.joinQueries_.size()); - for (auto jq : query.joinQueries_) { + result.reserve(query.GetJoinQueries().size()); + for (auto jq : query.GetJoinQueries()) { jq.Limit(reindexer::QueryEntry::kDefaultLimit); jq.Offset(reindexer::QueryEntry::kDefaultOffset); jq.sortingEntries_.clear(); @@ -842,23 +920,31 @@ class QueriesVerifier : public virtual ::testing::Test { return it->second; } - static void printFailedQueryEntries(const reindexer::QueryEntries& failedEntries, const std::vector& js) { + static void printFailedQueryEntries(const reindexer::QueryEntries& failedEntries, const std::vector& js, + const std::vector& subQueries) { TestCout() << "Failed entries: "; - printQueryEntries(failedEntries.cbegin(), failedEntries.cend(), js); + printQueryEntries(failedEntries.cbegin(), failedEntries.cend(), js, subQueries); TestCout() << std::endl << std::endl; } static void printQueryEntries(reindexer::QueryEntries::const_iterator it, reindexer::QueryEntries::const_iterator to, - const std::vector& js) { + const std::vector& js, const std::vector& subQueries) { TestCout() << "("; for (; it != to; ++it) { TestCout() << (it->operation == OpAnd ? "AND" : (it->operation == OpOr ? "OR" : "NOT")); it->InvokeAppropriate( - [&it, &js](const reindexer::QueryEntriesBracket&) { printQueryEntries(it.cbegin(), it.cend(), js); }, + [&](const reindexer::QueryEntriesBracket&) { printQueryEntries(it.cbegin(), it.cend(), js, subQueries); }, [](const reindexer::QueryEntry& qe) { TestCout() << qe.Dump(); }, [&js](const reindexer::JoinQueryEntry& jqe) { TestCout() << jqe.Dump(js); }, [](const reindexer::BetweenFieldsQueryEntry& qe) { TestCout() << qe.Dump(); }, - [](const reindexer::AlwaysFalse&) { TestCout() << "Always False"; }); + [&subQueries](const reindexer::SubQueryEntry& sqe) { + TestCout() << '(' << subQueries.at(sqe.QueryIndex()).GetSQL() << ") " << sqe.Condition(); + }, + [&subQueries](const reindexer::SubQueryFieldEntry& sqe) { + TestCout() << sqe.FieldName() << ' ' << sqe.Condition() << " (" << subQueries.at(sqe.QueryIndex()).GetSQL() << ')'; + }, + [](const reindexer::AlwaysFalse&) { TestCout() << "Always False"; }, + [](const reindexer::AlwaysTrue&) { TestCout() << "Always True"; }); } TestCout() << ")"; } diff --git a/cpp_src/gtests/tests/fixtures/replication_api.cc b/cpp_src/gtests/tests/fixtures/replication_api.cc index 66ca8a4aa..f37846a54 100644 --- a/cpp_src/gtests/tests/fixtures/replication_api.cc +++ b/cpp_src/gtests/tests/fixtures/replication_api.cc @@ -6,8 +6,6 @@ #include "tools/fsops.h" #include "vendor/gason/gason.h" -const std::string ReplicationApi::kStoragePath = "/tmp/reindex_repl_test/"; -// const std::string ReplicationApi::kReplicationConfigFilename = "replication.conf"; const std::string ReplicationApi::kConfigNs = "#config"; bool ReplicationApi::StopServer(size_t id) { diff --git a/cpp_src/gtests/tests/fixtures/replication_api.h b/cpp_src/gtests/tests/fixtures/replication_api.h index 455715321..19e2cf9ce 100644 --- a/cpp_src/gtests/tests/fixtures/replication_api.h +++ b/cpp_src/gtests/tests/fixtures/replication_api.h @@ -23,8 +23,6 @@ const auto kMaxForceSyncCmdTime = std::chrono::seconds(10); class ReplicationApi : public ::testing::Test { public: - static const std::string kStoragePath; - static const std::string kReplicationConfigFilename; static const std::string kConfigNs; void SetUp(); @@ -55,6 +53,7 @@ class ReplicationApi : public ::testing::Test { shared_timed_mutex restartMutex_; private: + const std::string kStoragePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex_repl_test/"); std::vector svc_; mutable std::mutex m_; }; diff --git a/cpp_src/gtests/tests/fixtures/replication_load_api.h b/cpp_src/gtests/tests/fixtures/replication_load_api.h index 749f11ebf..ddbbf1fa2 100644 --- a/cpp_src/gtests/tests/fixtures/replication_load_api.h +++ b/cpp_src/gtests/tests/fixtures/replication_load_api.h @@ -130,7 +130,7 @@ class ReplicationLoadApi : public ReplicationApi { assertrx(num); auto srv = GetSrv(num); auto curConfig = srv->GetServerConfig(ServerControl::ConfigType::File); - EXPECT_TRUE(config == curConfig); + EXPECT_TRUE(config == curConfig) << "config:\n" << config.GetJSON() << "\ncurConfig:\n" << curConfig.GetJSON(); } void CheckSlaveConfigNamespace(size_t num, const ReplicationConfigTest &config, std::chrono::seconds awaitTime) { assertrx(num); @@ -142,7 +142,8 @@ class ReplicationLoadApi : public ReplicationApi { } std::this_thread::sleep_for(std::chrono::seconds(1)); } - EXPECT_TRUE(config == srv->GetServerConfig(ServerControl::ConfigType::Namespace)); + auto curConfig = srv->GetServerConfig(ServerControl::ConfigType::Namespace); + EXPECT_TRUE(config == curConfig) << "config:\n" << config.GetJSON() << "\ncurConfig:\n" << curConfig.GetJSON(); } std::atomic_bool stop; diff --git a/cpp_src/gtests/tests/fixtures/rpcclient_api.h b/cpp_src/gtests/tests/fixtures/rpcclient_api.h index 5edb3ffd5..470331401 100644 --- a/cpp_src/gtests/tests/fixtures/rpcclient_api.h +++ b/cpp_src/gtests/tests/fixtures/rpcclient_api.h @@ -7,6 +7,7 @@ #include "client/reindexer.h" #include "replicator/updatesobserver.h" #include "server/server.h" +#include "tools/fsops.h" #include "client/cororeindexer.h" @@ -107,7 +108,7 @@ class RPCClientTestApi : public ::testing::Test { void FillData(reindexer::client::Reindexer& rx, std::string_view nsName, int from, int count); void FillData(reindexer::client::CoroReindexer& rx, std::string_view nsName, int from, int count); - const std::string_view kDbPrefix{"/tmp/reindex/rpc_client_test"}; + const std::string kDbPrefix{reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex/rpc_client_test")}; private: struct ServerData { diff --git a/cpp_src/gtests/tests/fixtures/servercontrol.cc b/cpp_src/gtests/tests/fixtures/servercontrol.cc index bcbfc80f2..718de3ad9 100644 --- a/cpp_src/gtests/tests/fixtures/servercontrol.cc +++ b/cpp_src/gtests/tests/fixtures/servercontrol.cc @@ -12,6 +12,27 @@ using namespace reindexer; +std::string ReplicationConfigTest::GetJSON() const { + WrSerializer ser; + { + JsonBuilder builder(ser); + + builder.Put("role", role_); + builder.Put("server_id", serverId_); + builder.Put("dsn", dsn_); + builder.Put("app_name", appName_); + builder.Put("force_sync_on_logic_error", forceSyncOnLogicError_); + builder.Put("force_sync_on_wrong_datahash", forceSyncOnWrongDataHash_); + { + auto jsn = builder.Array("namespaces"); + for (auto& ns : namespaces_) { + jsn.Put(nullptr, ns); + } + } + } + return std::string(ser.Slice()); +} + ServerControl::Interface::~Interface() { Stop(); if (tr) { diff --git a/cpp_src/gtests/tests/fixtures/servercontrol.h b/cpp_src/gtests/tests/fixtures/servercontrol.h index 86a4154ab..c034588a3 100644 --- a/cpp_src/gtests/tests/fixtures/servercontrol.h +++ b/cpp_src/gtests/tests/fixtures/servercontrol.h @@ -9,6 +9,7 @@ #include "estl/shared_mutex.h" #include "reindexertestapi.h" #include "server/server.h" +#include "tools/fsops.h" #include "tools/stringstools.h" #ifdef REINDEXER_WITH_SC_AS_PROCESS @@ -44,6 +45,8 @@ struct ReplicationConfigTest { namespaces_ == config.namespaces_ && serverId_ == config.serverId_; } + std::string GetJSON() const; + std::string role_; bool forceSyncOnLogicError_; bool forceSyncOnWrongDataHash_; @@ -67,7 +70,7 @@ class ServerControl { public: const std::string kReplicationConfigFilename = "replication.conf"; const std::string kConfigNs = "#config"; - const std::string kStoragePath = "/tmp/reindex_repl_test/"; + const std::string kStoragePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex_repl_test"); const unsigned short kDefaultHttpPort = 5555; const size_t kMaxServerStartTimeSec = 20; diff --git a/cpp_src/gtests/tests/fixtures/storage_lazy_load.h b/cpp_src/gtests/tests/fixtures/storage_lazy_load.h index c32ec7caf..bc4bfe2a3 100644 --- a/cpp_src/gtests/tests/fixtures/storage_lazy_load.h +++ b/cpp_src/gtests/tests/fixtures/storage_lazy_load.h @@ -106,7 +106,7 @@ class DISABLED_StorageLazyLoadApi : public ReindexerApi { const char* kFieldId = "id"; const char* kFieldRandomName = "random_name"; const char* kConfigNamespace = "#config"; - const std::string kStoragePath = "/tmp/reindex/lazy_load_test"; + const std::string kStoragePath = reindexer::fs::JoinPath(reindexer::fs::GetTempDir(), "reindex/lazy_load_test"); const char* jsonConfigTemplate = R"json({ "type":"namespaces", "namespaces":[ diff --git a/cpp_src/gtests/tests/fuzzing/fuzzing.cc b/cpp_src/gtests/tests/fuzzing/fuzzing.cc index fb71502d8..55a109b64 100644 --- a/cpp_src/gtests/tests/fuzzing/fuzzing.cc +++ b/cpp_src/gtests/tests/fuzzing/fuzzing.cc @@ -104,7 +104,7 @@ TEST_F(Fuzzing, BaseTest) { auto err = rx_.Select(query, qr); EXPECT_TRUE(err.ok()) << err.what(); if (err.ok()) { - Verify(qr, query, rx_); + Verify(qr, std::move(query), rx_); } } } catch (const std::exception& err) { diff --git a/cpp_src/gtests/tests/unit/dsl_parser_test.cc b/cpp_src/gtests/tests/unit/dsl_parser_test.cc index 2fb4bb4c7..8ca312173 100644 --- a/cpp_src/gtests/tests/unit/dsl_parser_test.cc +++ b/cpp_src/gtests/tests/unit/dsl_parser_test.cc @@ -33,8 +33,8 @@ TEST_F(JoinSelectsApi, MergedQueriesDSLTest) { Query firstMergedQuery{Query(books_namespace, 10, 100).Where(pages, CondLe, 250)}; Query secondMergedQuery{Query(books_namespace, 100, 50).Where(bookid, CondGe, 100)}; - mainBooksQuery.mergeQueries_.emplace_back(Merge, std::move(firstMergedQuery)); - mainBooksQuery.mergeQueries_.emplace_back(Merge, std::move(secondMergedQuery)); + mainBooksQuery.Merge(std::move(firstMergedQuery)); + mainBooksQuery.Merge(std::move(secondMergedQuery)); checkQueryDslParse(mainBooksQuery); } @@ -47,21 +47,14 @@ TEST_F(JoinSelectsApi, AggregateFunctonsDSLTest) { } TEST_F(JoinSelectsApi, SelectFilterDSLTest) { - Query query{Query(books_namespace, 10, 100).Where(pages, CondGe, 150)}; - query.selectFilter_.push_back(price); - query.selectFilter_.push_back(pages); - query.selectFilter_.push_back(title); + Query query{Query(books_namespace, 10, 100).Where(pages, CondGe, 150).Select({price, pages, title})}; checkQueryDslParse(query); } TEST_F(JoinSelectsApi, SelectFilterInJoinDSLTest) { - Query queryBooks(books_namespace, 0, 10); - queryBooks.selectFilter_.push_back(price); - queryBooks.selectFilter_.push_back(title); + Query queryBooks = Query(books_namespace, 0, 10).Select({price, title}); { - Query queryAuthors(authors_namespace); - queryAuthors.selectFilter_.push_back(authorid); - queryAuthors.selectFilter_.push_back(age); + Query queryAuthors = Query(authors_namespace).Select({authorid, age}); queryBooks.LeftJoin(authorid_fk, authorid, CondEq, std::move(queryAuthors)); } @@ -100,11 +93,9 @@ TEST_F(JoinSelectsApi, GeneralDSLTest) { Query innerJoinQuery = queryBooks.InnerJoin(authorid_fk, authorid, CondEq, std::move(queryAuthors)); Query testDslQuery = innerJoinQuery.OrInnerJoin(genreId_fk, genreid, CondEq, std::move(queryGenres)); - testDslQuery.mergeQueries_.emplace_back(Merge, std::move(queryBooks)); - testDslQuery.mergeQueries_.emplace_back(Merge, std::move(innerJoinQuery)); - testDslQuery.selectFilter_.push_back(genreid); - testDslQuery.selectFilter_.push_back(bookid); - testDslQuery.selectFilter_.push_back(authorid_fk); + testDslQuery.Merge(std::move(queryBooks)); + testDslQuery.Merge(std::move(innerJoinQuery)); + testDslQuery.Select({genreid, bookid, authorid_fk}); testDslQuery.AddFunction("f1()"); testDslQuery.AddFunction("f2()"); testDslQuery.aggregations_.push_back({AggDistinct, {bookid}}); diff --git a/cpp_src/gtests/tests/unit/equalposition_tests.cc b/cpp_src/gtests/tests/unit/equalposition_tests.cc index d3e1538e6..32b17cf67 100644 --- a/cpp_src/gtests/tests/unit/equalposition_tests.cc +++ b/cpp_src/gtests/tests/unit/equalposition_tests.cc @@ -244,15 +244,13 @@ TEST_F(EqualPositionApi, EmptyCompOpErr) { } { QueryResults qr; - Query q; - q.FromSQL("SELECT * FROM ns2 WHERE a1=10 AND a2=20 equal_position(a1, a2)"); + Query q = Query::FromSQL("SELECT * FROM ns2 WHERE a1=10 AND a2=20 equal_position(a1, a2)"); err = rt.reindexer->Select(q, qr); EXPECT_TRUE(err.ok()) << err.what(); } { QueryResults qr; - Query q; - q.FromSQL("SELECT * FROM ns2 WHERE a1 IS NULL AND a2=20 equal_position(a1, a2)"); + Query q = Query::FromSQL("SELECT * FROM ns2 WHERE a1 IS NULL AND a2=20 equal_position(a1, a2)"); err = rt.reindexer->Select(q, qr); EXPECT_TRUE(err.what() == "Condition IN(with empty parameter list), IS NULL, IS EMPTY not allowed for equal position!") << err.what(); @@ -260,8 +258,7 @@ TEST_F(EqualPositionApi, EmptyCompOpErr) { } { QueryResults qr; - Query q; - q.FromSQL("SELECT * FROM ns2 WHERE a1 =10 AND a2 IS EMPTY equal_position(a1, a2)"); + Query q = Query::FromSQL("SELECT * FROM ns2 WHERE a1 =10 AND a2 IS EMPTY equal_position(a1, a2)"); err = rt.reindexer->Select(q, qr); EXPECT_TRUE(err.what() == "Condition IN(with empty parameter list), IS NULL, IS EMPTY not allowed for equal position!") << err.what(); @@ -269,8 +266,7 @@ TEST_F(EqualPositionApi, EmptyCompOpErr) { } { QueryResults qr; - Query q; - q.FromSQL("SELECT * FROM ns2 WHERE a1 IN () AND a2 IS EMPTY equal_position(a1, a2)"); + Query q = Query::FromSQL("SELECT * FROM ns2 WHERE a1 IN () AND a2 IS EMPTY equal_position(a1, a2)"); err = rt.reindexer->Select(q, qr); EXPECT_TRUE(err.what() == "Condition IN(with empty parameter list), IS NULL, IS EMPTY not allowed for equal position!") << err.what(); @@ -298,8 +294,7 @@ TEST_F(EqualPositionApi, SamePositionFromSql) { QueryResults qr; // SQL query contains equal_position() for field 'a1' twice const std::string_view sql = "select * from test_namespace where a1 > 0 and a1 < 10 equal_position(a1, a1)"; - Query q; - q.FromSQL(sql); + Query q = Query::FromSQL(sql); // Make sure processing this query leads to error const Error err = rt.reindexer->Select(q, qr); EXPECT_FALSE(err.ok()); diff --git a/cpp_src/gtests/tests/unit/ft/ft_generic.cc b/cpp_src/gtests/tests/unit/ft/ft_generic.cc index 08ef6a7dc..5b4c03b6e 100644 --- a/cpp_src/gtests/tests/unit/ft/ft_generic.cc +++ b/cpp_src/gtests/tests/unit/ft/ft_generic.cc @@ -127,7 +127,7 @@ TEST_P(FTGenericApi, MergeWithSameNSAndSelectFunctions) { auto mqr{reindexer::Query("nm1").Where("ft3", CondEq, std::move(dsl))}; mqr.AddFunction(field + " = snippet(,\"\",3,2,,d)"); - qr.mergeQueries_.emplace_back(Merge, std::move(mqr)); + qr.Merge(std::move(mqr)); qr.AddFunction(field + " = highlight(,)"); auto err = rt.reindexer->Select(qr, res); EXPECT_TRUE(err.ok()) << err.what(); diff --git a/cpp_src/gtests/tests/unit/join_test.cc b/cpp_src/gtests/tests/unit/join_test.cc index 17aee3df6..6fb37ea94 100644 --- a/cpp_src/gtests/tests/unit/join_test.cc +++ b/cpp_src/gtests/tests/unit/join_test.cc @@ -63,8 +63,7 @@ TEST_F(JoinSelectsApi, JoinsAsWhereConditionsTest2) { "OR INNER JOIN (SELECT *FROM authors_namespace WHERE authorid >= 300 AND authorid <= 400) ON authors_namespace.authorid = " "books_namespace.authorid_fk LIMIT 50"; - Query query; - query.FromSQL(sql); + Query query = Query::FromSQL(sql); QueryWatcher watcher{query}; reindexer::QueryResults qr; Error err = rt.reindexer->Select(query, qr); @@ -82,23 +81,20 @@ TEST_F(JoinSelectsApi, SqlPasringTest) { "(authorid >= 10 AND authorid <= 20) limit 100) on " "authors_namespace.authorid = books_namespace.authorid_fk) or pages == 3 limit 20"; - Query srcQuery; - srcQuery.FromSQL(sql); + Query srcQuery = Query::FromSQL(sql); QueryWatcher watcher{srcQuery}; reindexer::WrSerializer wrser; srcQuery.GetSQL(wrser); - Query dstQuery; - dstQuery.FromSQL(wrser.Slice()); + Query dstQuery = Query::FromSQL(wrser.Slice()); ASSERT_EQ(srcQuery, dstQuery); wrser.Reset(); srcQuery.Serialize(wrser); - Query deserializedQuery; reindexer::Serializer ser(wrser.Buf(), wrser.Len()); - deserializedQuery.Deserialize(ser); + Query deserializedQuery = Query::Deserialize(ser); ASSERT_EQ(srcQuery, deserializedQuery) << "Original query:\n" << srcQuery.GetSQL() << "\nDeserialized query:\n" << deserializedQuery.GetSQL(); @@ -513,13 +509,12 @@ static void checkForAllowedJsonTags(const std::vector& tags, gason: } TEST_F(JoinSelectsApi, JoinWithSelectFilter) { - Query queryAuthors(authors_namespace); - queryAuthors.selectFilter_.emplace_back(name); - queryAuthors.selectFilter_.emplace_back(age); + Query queryAuthors = Query(authors_namespace).Select({name, age}); - Query queryBooks{Query(books_namespace).Where(pages, CondGe, 100).InnerJoin(authorid_fk, authorid, CondEq, std::move(queryAuthors))}; - queryBooks.selectFilter_.emplace_back(title); - queryBooks.selectFilter_.emplace_back(price); + Query queryBooks{Query(books_namespace) + .Where(pages, CondGe, 100) + .InnerJoin(authorid_fk, authorid, CondEq, std::move(queryAuthors)) + .Select({title, price})}; QueryResults qr; Error err = rt.reindexer->Select(queryBooks, qr); @@ -563,7 +558,7 @@ TEST_F(JoinSelectsApi, TestMergeWithJoins) { // Build the 2nd query (with join) with 'authors_namespace' as the main NS. Query queryAuthors = Query(authors_namespace); queryAuthors.LeftJoin(locationid_fk, locationid, CondEq, Query(location_namespace)); - queryBooks.mergeQueries_.emplace_back(Merge, std::move(queryAuthors)); + queryBooks.Merge(std::move(queryAuthors)); // Execute it QueryResults qr; @@ -640,8 +635,7 @@ TEST_F(JoinOnConditionsApi, TestGeneralConditions) { const std::string sqlTemplate = R"(select * from books_namespace inner join books_namespace on (books_namespace.authorid_fk = books_namespace.authorid_fk and books_namespace.pages %s books_namespace.pages);)"; for (CondType condition : {CondLt, CondLe, CondGt, CondGe, CondEq}) { - Query queryBooks; - queryBooks.FromSQL(GetSql(sqlTemplate, condition)); + Query queryBooks = Query::FromSQL(GetSql(sqlTemplate, condition)); QueryResults qr; Error err = rt.reindexer->Select(queryBooks, qr); ASSERT_TRUE(err.ok()) << err.what(); @@ -678,14 +672,12 @@ TEST_F(JoinOnConditionsApi, TestComparisonConditions) { for (size_t i = 0; i < sqlTemplates.size(); ++i) { const auto& sqlTemplate = sqlTemplates[i]; for (const auto& condition : conditions) { - Query query1; - query1.FromSQL(GetSql(sqlTemplate.first, condition.first)); + Query query1 = Query::FromSQL(GetSql(sqlTemplate.first, condition.first)); QueryResults qr1; Error err = rt.reindexer->Select(query1, qr1); ASSERT_TRUE(err.ok()) << err.what(); - Query query2; - query2.FromSQL(GetSql(sqlTemplate.second, condition.second)); + Query query2 = Query::FromSQL(GetSql(sqlTemplate.second, condition.second)); QueryResults qr2; err = rt.reindexer->Select(query2, qr2); ASSERT_TRUE(err.ok()) << err.what(); @@ -770,8 +762,7 @@ TEST_F(JoinOnConditionsApi, TestLeftJoinOnCondSet) { } auto sqlTestCase = [execQuery](const std::string& s) { - Query q; - q.FromSQL(s); + Query q = Query::FromSQL(s); execQuery(q); }; @@ -788,8 +779,7 @@ TEST_F(JoinOnConditionsApi, TestInvalidConditions) { R"(select * from books_namespace inner join authors_namespace on (books_namespace.authorid_fk = books_namespace.authorid_fk and books_namespace.pages in(1, 50, 100, 500, 1000, 1500));)", }; for (const std::string& sql : sqls) { - Query queryBooks; - EXPECT_THROW(queryBooks.FromSQL(sql), Error); + EXPECT_THROW((void)Query::FromSQL(sql), Error); } QueryResults qr; Error err = rt.reindexer->Select(Query(books_namespace).InnerJoin(authorid_fk, authorid, CondAllSet, Query(authors_namespace)), qr); diff --git a/cpp_src/gtests/tests/unit/msgpack_cproto_tests.cc b/cpp_src/gtests/tests/unit/msgpack_cproto_tests.cc index a991e0bdc..b3b191f1b 100644 --- a/cpp_src/gtests/tests/unit/msgpack_cproto_tests.cc +++ b/cpp_src/gtests/tests/unit/msgpack_cproto_tests.cc @@ -124,8 +124,7 @@ TEST_F(MsgPackCprotoApi, ModifyItemsTest) { TEST_F(MsgPackCprotoApi, UpdateTest) { const std::string_view sql = "update test_namespace set a1 = 7 where id >= 10 and id <= 100"; - Query q; - q.FromSQL(sql); + Query q = Query::FromSQL(sql); reindexer::client::QueryResults qr; Error err = client_->Update(q, qr, ctx_, FormatMsgPack); @@ -153,8 +152,7 @@ TEST_F(MsgPackCprotoApi, UpdateTest) { TEST_F(MsgPackCprotoApi, DeleteTest) { const std::string_view sql = "delete from test_namespace where id >= 100 and id <= 110"; - Query q; - q.FromSQL(sql); + Query q = Query::FromSQL(sql); reindexer::client::QueryResults qr; Error err = client_->Delete(q, qr, ctx_, FormatMsgPack); diff --git a/cpp_src/gtests/tests/unit/namespace_test.cc b/cpp_src/gtests/tests/unit/namespace_test.cc index d0b85f90d..2e3fbcf93 100644 --- a/cpp_src/gtests/tests/unit/namespace_test.cc +++ b/cpp_src/gtests/tests/unit/namespace_test.cc @@ -5,13 +5,11 @@ #include "core/cjson/jsonbuilder.h" #include "core/cjson/msgpackbuilder.h" #include "core/cjson/msgpackdecoder.h" -#include "core/itemimpl.h" #include "estl/span.h" #include "ns_api.h" #include "tools/jsontools.h" #include "tools/serializer.h" #include "vendor/gason/gason.h" -#include "vendor/msgpack/msgpack.h" TEST_F(NsApi, IndexDrop) { Error err = rt.reindexer->OpenNamespace(default_namespace); @@ -494,6 +492,44 @@ TEST_F(NsApi, TestUpdateTwoFields) { } } +TEST_F(NsApi, TestUpdateNewFieldCheckTmVersion) { + DefineDefaultNamespace(); + FillDefaultNamespace(); + + auto check = [this](const Query &query, int tmVersion) { + QueryResults qrUpdate; + auto err = rt.reindexer->Update(query, qrUpdate); + ASSERT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(qrUpdate.Count(), 1); + ASSERT_EQ(qrUpdate.getTagsMatcher(0).version(), tmVersion); + }; + + QueryResults qr; + Error err = rt.reindexer->Select(Query(default_namespace).Where(idIdxName, CondEq, 1), qr); + ASSERT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(qr.Count(), 1); + auto tmVersion = qr.getTagsMatcher(0).version(); + Query updateQuery = Query(default_namespace).Where(idIdxName, CondEq, 1).Set("some_new_field", "some_value"); + + // Make sure the version increases by 1 when one new tag with non-object content is added + check(updateQuery, ++tmVersion); + + // Make sure the version not change when the same update query applied + check(updateQuery, tmVersion); + + updateQuery.SetObject("new_obj_field", R"({"id":111, "name":"successfully updated!"})"); + + // Make sure that tm version updates correctly when new tags are added: + // +1 by tag very_nested, + // +1 by all new tags processed in ItemModifier::modifyCJSON for SetObject-method + // +1 by merge of two corresponded tagsmatchers + check(updateQuery, tmVersion += 3); + + // Make sure that if no new tags were added to the tagsmatcher during the update, + // then the version of the tagsmatcher will not change + check(updateQuery, tmVersion); +} + static void updateArrayField(const std::shared_ptr &reindexer, const std::string &ns, const std::string &updateFieldPath, const VariantArray &values) { QueryResults qrUpdate; @@ -863,8 +899,7 @@ TEST_F(NsApi, SetArrayFieldWithSql) { AddUnindexedData(); // 3. Set all items of array to 777 - Query updateQuery; - updateQuery.FromSQL("update test_namespace set nested.nested_array[1].prices[*] = 777"); + Query updateQuery = Query::FromSQL("update test_namespace set nested.nested_array[1].prices[*] = 777"); QueryResults qrUpdate; Error err = rt.reindexer->Update(updateQuery, qrUpdate); ASSERT_TRUE(err.ok()) << err.what(); @@ -889,8 +924,7 @@ TEST_F(NsApi, DropArrayFieldWithSql) { AddUnindexedData(); // 3. Drop all items of array nested.nested_array[1].prices - Query updateQuery; - updateQuery.FromSQL("update test_namespace drop nested.nested_array[1].prices[*]"); + Query updateQuery = Query::FromSQL("update test_namespace drop nested.nested_array[1].prices[*]"); QueryResults qrUpdate; Error err = rt.reindexer->Update(updateQuery, qrUpdate); ASSERT_TRUE(err.ok()) << err.what(); @@ -913,8 +947,7 @@ TEST_F(NsApi, ExtendArrayFromTopWithSql) { AddUnindexedData(); // Append the following items: [88, 88, 88] to the top of the array array_field - Query updateQuery; - updateQuery.FromSQL("update test_namespace set array_field = [88,88,88] || array_field"); + Query updateQuery = Query::FromSQL("update test_namespace set array_field = [88,88,88] || array_field"); QueryResults qrUpdate; Error err = rt.reindexer->Update(updateQuery, qrUpdate); ASSERT_TRUE(err.ok()) << err.what(); @@ -940,8 +973,8 @@ TEST_F(NsApi, AppendToArrayWithSql) { AddUnindexedData(); // 3. Extend array_field with expression substantially - Query updateQuery; - updateQuery.FromSQL("update test_namespace set array_field = array_field || objects.more[1].array[4] || [22,22,22] || [11]"); + Query updateQuery = + Query::FromSQL("update test_namespace set array_field = array_field || objects.more[1].array[4] || [22,22,22] || [11]"); QueryResults qrUpdate; Error err = rt.reindexer->Update(updateQuery, qrUpdate); ASSERT_TRUE(err.ok()) << err.what(); @@ -1122,8 +1155,8 @@ TEST_F(NsApi, UpdateObjectsArray) { AddUnindexedData(); // 3. Update object array and change one of it's items - Query updateQuery; - updateQuery.FromSQL(R"(update test_namespace set nested.nested_array[1] = {"id":1,"name":"modified", "prices":[4,5,6]})"); + Query updateQuery = + Query::FromSQL(R"(update test_namespace set nested.nested_array[1] = {"id":1,"name":"modified", "prices":[4,5,6]})"); QueryResults qrUpdate; Error err = rt.reindexer->Update(updateQuery, qrUpdate); ASSERT_TRUE(err.ok()) << err.what(); @@ -1143,8 +1176,7 @@ TEST_F(NsApi, UpdateObjectsArray2) { AddUnindexedData(); // 3. Set all items of the object array to a new value - Query updateQuery; - updateQuery.FromSQL(R"(update test_namespace set nested.nested_array[*] = {"ein":1,"zwei":2, "drei":3})"); + Query updateQuery = Query::FromSQL(R"(update test_namespace set nested.nested_array[*] = {"ein":1,"zwei":2, "drei":3})"); QueryResults qrUpdate; Error err = rt.reindexer->Update(updateQuery, qrUpdate); ASSERT_TRUE(err.ok()) << err.what(); @@ -1441,6 +1473,112 @@ TEST_F(NsApi, UpdateObjectsArray4) { } } +TEST_F(NsApi, UpdateArrayIndexFieldWithSeveralJsonPaths) { + struct Values { + std::vector valsList, newValsList; + }; + const int fieldsCnt = 5; + const int valsPerFieldCnt = 4; + std::vector fieldsValues(fieldsCnt); + for (int i = 0; i < fieldsCnt; ++i) { + for (int j = 0; j < valsPerFieldCnt; ++j) { + fieldsValues[i].valsList.emplace_back(fmt::sprintf("data%d%d", i, j)); + fieldsValues[i].newValsList.emplace_back(fmt::sprintf("data%d%d", i, j + i)); + } + } + + enum class OpT { Insert, Update }; + + auto makeFieldsList = [&fieldsValues](const reindexer::fast_hash_set &indexes, OpT type) { + auto quote = type == OpT::Insert ? '"' : '\''; + std::vector Values::*list = type == OpT::Insert ? &Values::valsList : &Values::newValsList; + const auto fieldsListTmplt = type == OpT::Insert ? R"("%sfield%d": [%s])" : R"(%sfield%d = [%s])"; + std::string fieldsList; + for (int idx : indexes) { + std::string fieldList; + for (const auto &data : fieldsValues[idx].*list) { + fieldList += std::string(fieldList.empty() ? "" : ", ") + quote + data + quote; + } + fieldsList += fmt::sprintf(fieldsListTmplt, fieldsList.empty() ? "" : ", ", idx, fieldList); + } + return fieldsList; + }; + + auto makeItem = [&makeFieldsList](int id, const reindexer::fast_hash_set &indexes) { + auto list = makeFieldsList(indexes, OpT::Insert); + return fmt::sprintf(R"({"id": %d%s})", id, (list.empty() ? "" : ", ") + list); + }; + + auto makeUpdate = [this, &makeFieldsList](int id, const reindexer::fast_hash_set &indexes) { + return fmt::sprintf("UPDATE %s SET %s WHERE id = %d", default_namespace, makeFieldsList(indexes, OpT::Update), id); + }; + + struct TestCase { + reindexer::fast_hash_set insertIdxs, updateIdxs; + auto expected() const { + auto res = insertIdxs; + res.insert(updateIdxs.begin(), updateIdxs.end()); + return res; + } + }; + + std::vector testCases{ + {{}, {0}}, + {{}, {2}}, + {{}, {0, 1, 2}}, + {{2, 3, 4}, {0}}, + {{3}, {0, 2, 4}}, + {{0, 3, 4}, {2, 1}}, + {{0, 1, 2, 3}, {4}}, + {{0, 1, 2}, {3, 4}}, + {{0, 2, 3}, {1, 4}}, + {{4}, {0, 1, 2, 3}}, + {{3, 4}, {0, 2, 1}}, + {{}, {0, 1, 2, 3, 4}}, + {{0, 1, 2, 3, 4}, {0}}, + {{0, 3, 4}, {0, 3, 4}}, + {{0, 1, 2}, {2, 3, 1}}, + {{0, 3, 4}, {2, 3, 4}}, + {{0, 1, 3}, {0, 1, 2, 3, 4}}, + {{0, 1, 2, 3, 4}, {0, 1, 2, 3, 4}}, + }; + + Error err = rt.reindexer->OpenNamespace(default_namespace); + ASSERT_TRUE(err.ok()) << err.what(); + + err = rt.reindexer->AddIndex(default_namespace, {"id", "hash", "int", IndexOpts().PK()}); + ASSERT_TRUE(err.ok()) << err.what(); + err = rt.reindexer->AddIndex(default_namespace, {"array_index", reindexer::JsonPaths{"field0", "field1", "field2", "field3", "field4"}, + "hash", "string", IndexOpts().Array()}); + ASSERT_TRUE(err.ok()) << err.what(); + + for (size_t i = 0; i < testCases.size(); ++i) { + AddItemFromJSON(default_namespace, makeItem(i, testCases[i].insertIdxs)); + { + QueryResults qr; + err = rt.reindexer->Select(makeUpdate(i, testCases[i].updateIdxs), qr); + ASSERT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(qr.Count(), 1); + + auto item = qr.begin().GetItem(false); + for (auto idx : testCases[i].expected()) { + int varArrCnt = 0; + for (auto &&var : VariantArray(item[fmt::sprintf("field%d", idx)])) { + const auto &data = testCases[i].updateIdxs.count(idx) ? fieldsValues[idx].newValsList : fieldsValues[idx].valsList; + ASSERT_EQ(var.As(), data[varArrCnt++]); + } + } + } + } + + // Check that prohibited updating an index array field with several json paths by index name + QueryResults qr; + err = rt.reindexer->Select(fmt::sprintf(R"(UPDATE %s SET array_index = ['data0', 'data1', 'data2'] WHERE id = 0)", default_namespace), + qr); + ASSERT_FALSE(err.ok()); + ASSERT_EQ(err.what(), "Ambiguity when updating field with several json paths by index name: 'array_index'"); +} + TEST_F(NsApi, UpdateWithObjectAndFieldsDuplication) { Error err = rt.reindexer->OpenNamespace(default_namespace); ASSERT_TRUE(err.ok()) << err.what(); @@ -1849,7 +1987,7 @@ TEST_F(NsApi, TestUpdatePkFieldNoConditions) { ASSERT_TRUE(err.ok()) << err.what(); QueryResults qr; - err = rt.reindexer->Select("update test_namespace set id = id + "+std::to_string(qrCount.totalCount+100), qr); + err = rt.reindexer->Select("update test_namespace set id = id + " + std::to_string(qrCount.totalCount + 100), qr); ASSERT_TRUE(err.ok()) << err.what(); ASSERT_GT(qr.Count(), 0); @@ -1857,7 +1995,7 @@ TEST_F(NsApi, TestUpdatePkFieldNoConditions) { for (auto &it : qr) { Item item = it.GetItem(false); Variant intFieldVal = item[idIdxName]; - ASSERT_EQ(static_cast(intFieldVal) , i+qrCount.totalCount+100); + ASSERT_EQ(static_cast(intFieldVal), i + qrCount.totalCount + 100); i++; } } @@ -2214,20 +2352,20 @@ static void checkQueryDsl(const Query &src) { } } if (objectValues) { - EXPECT_EQ(src.entries, dst.entries); + EXPECT_EQ(src.Entries(), dst.Entries()); EXPECT_EQ(src.aggregations_, dst.aggregations_); EXPECT_EQ(src.NsName(), dst.NsName()); EXPECT_EQ(src.sortingEntries_, dst.sortingEntries_); EXPECT_EQ(src.CalcTotal(), dst.CalcTotal()); EXPECT_EQ(src.Offset(), dst.Offset()); EXPECT_EQ(src.Limit(), dst.Limit()); - EXPECT_EQ(src.debugLevel, dst.debugLevel); - EXPECT_EQ(src.strictMode, dst.strictMode); + EXPECT_EQ(src.GetDebugLevel(), dst.GetDebugLevel()); + EXPECT_EQ(src.GetStrictMode(), dst.GetStrictMode()); EXPECT_EQ(src.forcedSortOrder_, dst.forcedSortOrder_); - EXPECT_EQ(src.selectFilter_, dst.selectFilter_); + EXPECT_EQ(src.SelectFilters(), dst.SelectFilters()); EXPECT_EQ(src.selectFunctions_, dst.selectFunctions_); - EXPECT_EQ(src.joinQueries_, dst.joinQueries_); - EXPECT_EQ(src.mergeQueries_, dst.mergeQueries_); + EXPECT_EQ(src.GetJoinQueries(), dst.GetJoinQueries()); + EXPECT_EQ(src.GetMergeQueries(), dst.GetMergeQueries()); } else { EXPECT_EQ(dst, src); } @@ -2237,45 +2375,38 @@ TEST_F(NsApi, TestModifyQueriesSqlEncoder) { const std::string sqlUpdate = "UPDATE ns SET field1 = 'mrf',field2 = field2+1,field3 = ['one','two','three','four','five'] WHERE a = true AND location = " "'msk'"; - Query q1; - q1.FromSQL(sqlUpdate); + Query q1 = Query::FromSQL(sqlUpdate); EXPECT_EQ(q1.GetSQL(), sqlUpdate); checkQueryDsl(q1); const std::string sqlDrop = "UPDATE ns DROP field1,field2 WHERE a = true AND location = 'msk'"; - Query q2; - q2.FromSQL(sqlDrop); + Query q2 = Query::FromSQL(sqlDrop); EXPECT_EQ(q2.GetSQL(), sqlDrop); checkQueryDsl(q2); const std::string sqlUpdateWithObject = R"(UPDATE ns SET field = {"id":0,"name":"apple","price":1000,"nested":{"n_id":1,"desription":"good","array":[{"id":1,"description":"first"},{"id":2,"description":"second"},{"id":3,"description":"third"}]},"bonus":7} WHERE a = true AND location = 'msk')"; - Query q3; - q3.FromSQL(sqlUpdateWithObject); + Query q3 = Query::FromSQL(sqlUpdateWithObject); EXPECT_EQ(q3.GetSQL(), sqlUpdateWithObject); checkQueryDsl(q3); const std::string sqlTruncate = R"(TRUNCATE ns)"; - Query q4; - q4.FromSQL(sqlTruncate); + Query q4 = Query::FromSQL(sqlTruncate); EXPECT_EQ(q4.GetSQL(), sqlTruncate); checkQueryDsl(q4); const std::string sqlArrayAppend = R"(UPDATE ns SET array = array||[1,2,3]||array2||objects[0].nested.prices[0])"; - Query q5; - q5.FromSQL(sqlArrayAppend); + Query q5 = Query::FromSQL(sqlArrayAppend); EXPECT_EQ(q5.GetSQL(), sqlArrayAppend); checkQueryDsl(q5); const std::string sqlIndexUpdate = R"(UPDATE ns SET objects[0].nested.prices[*] = 'NE DOROGO!')"; - Query q6; - q6.FromSQL(sqlIndexUpdate); + Query q6 = Query::FromSQL(sqlIndexUpdate); EXPECT_EQ(q6.GetSQL(), sqlIndexUpdate); checkQueryDsl(q6); const std::string sqlSpeccharsUpdate = R"(UPDATE ns SET f1 = 'HELLO\n\r\b\f',f2 = '\t',f3 = '\"')"; - Query q7; - q7.FromSQL(sqlSpeccharsUpdate); + Query q7 = Query::FromSQL(sqlSpeccharsUpdate); EXPECT_EQ(q7.GetSQL(), sqlSpeccharsUpdate); checkQueryDsl(q7); } diff --git a/cpp_src/gtests/tests/unit/queries_test.cc b/cpp_src/gtests/tests/unit/queries_test.cc index 725fa47d6..5e862b295 100644 --- a/cpp_src/gtests/tests/unit/queries_test.cc +++ b/cpp_src/gtests/tests/unit/queries_test.cc @@ -1,5 +1,7 @@ #include + #include + #include "core/cjson/csvbuilder.h" #include "core/schema.h" #include "csv2jsonconverter.h" @@ -230,6 +232,16 @@ TEST_F(QueriesApi, SqlParseGenerate) { Query{"test_namespace"}.Sort("index", true, {"str1", "str2", "str3"})}, {"SELECT * FROM test_namespace ORDER BY FIELD(index, {10, 'str1'}, {20, 'str2'}, {30, 'str3'})", Query{"test_namespace"}.Sort("index", false, std::vector>{{10, "str1"}, {20, "str2"}, {30, "str3"}})}, + {"SELECT * FROM main_ns WHERE (SELECT * FROM second_ns WHERE id < 10 LIMIT 0) IS NOT NULL", + Query{"main_ns"}.Where(Query{"second_ns"}.Where("id", CondLt, 10), CondAny, VariantArray{})}, + {"SELECT * FROM main_ns WHERE id = (SELECT id FROM second_ns WHERE id < 10)", + Query{"main_ns"}.Where("id", CondEq, Query{"second_ns"}.Select({"id"}).Where("id", CondLt, 10))}, + {"SELECT * FROM main_ns WHERE (SELECT max(id) FROM second_ns WHERE id < 10) > 18", + Query{"main_ns"}.Where(Query{"second_ns"}.Aggregate(AggMax, {"id"}).Where("id", CondLt, 10), CondGt, {18})}, + {"SELECT * FROM main_ns WHERE id > (SELECT avg(id) FROM second_ns WHERE id < 10)", + Query{"main_ns"}.Where("id", CondGt, Query{"second_ns"}.Aggregate(AggAvg, {"id"}).Where("id", CondLt, 10))}, + {"SELECT * FROM main_ns WHERE id > (SELECT COUNT(*) FROM second_ns WHERE id < 10 LIMIT 0)", + Query{"main_ns"}.Where("id", CondGt, Query{"second_ns"}.Where("id", CondLt, 10).ReqTotal())}, }; for (const auto& [sql, expected, direction] : cases) { @@ -239,20 +251,18 @@ TEST_F(QueriesApi, SqlParseGenerate) { EXPECT_EQ(q.GetSQL(), sql); } if (direction & PARSE) { - Query parsed; try { - parsed.FromSQL(sql); + Query parsed = Query::FromSQL(sql); + EXPECT_EQ(parsed, q) << sql; } catch (const Error& err) { ADD_FAILURE() << "Unexpected error: " << err.what() << "\nSQL: " << sql; continue; } - EXPECT_EQ(parsed, q) << sql; } } else { const Error& expectedErr = std::get(expected); - Query parsed; try { - parsed.FromSQL(sql); + Query parsed = Query::FromSQL(sql); ADD_FAILURE() << "Expected error: " << expectedErr.what() << "\nSQL: " << sql; } catch (const Error& err) { EXPECT_EQ(err.what(), expectedErr.what()) << "\nSQL: " << sql; @@ -268,25 +278,329 @@ TEST_F(QueriesApi, DslGenerateParse) { std::string dsl; std::variant expected; Direction direction = BOTH; - } cases[]{ - {R"({"namespace":")"s + geomNs + - R"(","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"dwithin","field":")" + - kFieldNamePointLinearRTree + R"(","value":[[-9.2,-0.145],0.581]}],"merge_queries":[],"aggregations":[]})", - Query{geomNs}.DWithin(kFieldNamePointLinearRTree, reindexer::Point{-9.2, -0.145}, 0.581)}, - {R"({"namespace":")"s + default_namespace + - R"(","limit":-1,"offset":0,"req_total":"disabled","explain":false,"type":"select","select_with_rank":false,"select_filter":[],"select_functions":[],"sort":[],"filters":[{"op":"and","cond":"gt","first_field":")" + - kFieldNameStartTime + R"(","second_field":")" + kFieldNamePackages + R"("}],"merge_queries":[],"aggregations":[]})", - Query{Query(default_namespace).WhereBetweenFields(kFieldNameStartTime, CondGt, kFieldNamePackages)}}}; + } cases[]{{fmt::sprintf( + R"({ + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "always": true + } + ], + "merge_queries": [], + "aggregations": [] +})", + geomNs), + Query{geomNs}.AppendQueryEntry(OpAnd)}, + {fmt::sprintf( + R"({ + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "dwithin", + "field": "%s", + "value": [ + [ + -9.2, + -0.145 + ], + 0.581 + ] + } + ], + "merge_queries": [], + "aggregations": [] +})", + geomNs, kFieldNamePointLinearRTree), + Query{geomNs}.DWithin(kFieldNamePointLinearRTree, reindexer::Point{-9.2, -0.145}, 0.581)}, + {fmt::sprintf( + R"({ + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "gt", + "first_field": "%s", + "second_field": "%s" + } + ], + "merge_queries": [], + "aggregations": [] +})", + default_namespace, kFieldNameStartTime, kFieldNamePackages), + Query(default_namespace).WhereBetweenFields(kFieldNameStartTime, CondGt, kFieldNamePackages)}, + {fmt::sprintf( + R"({ + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "gt", + "subquery": { + "namespace": "%s", + "limit": 10, + "offset": 10, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [], + "merge_queries": [], + "aggregations": [ + { + "type": "max", + "sort": [], + "fields": [ + "%s" + ] + } + ] + }, + "value": 18 + } + ], + "merge_queries": [], + "aggregations": [] +})", + default_namespace, joinNs, kFieldNameAge), + Query(default_namespace).Where(Query(joinNs).Aggregate(AggMax, {kFieldNameAge}).Limit(10).Offset(10), CondGt, {18})}, + {fmt::sprintf( + R"({ + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "any", + "subquery": { + "namespace": "%s", + "limit": 0, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "eq", + "field": "%s", + "value": 1 + } + ], + "merge_queries": [], + "aggregations": [] + } + } + ], + "merge_queries": [], + "aggregations": [] +})", + default_namespace, joinNs, kFieldNameId), + Query(default_namespace).Where(Query(joinNs).Where(kFieldNameId, CondEq, 1), CondAny, {})}, + {fmt::sprintf( + R"({ + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "eq", + "field": "%s", + "subquery": { + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [ + "%s" + ], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "set", + "field": "%s", + "value": [ + 1, + 10, + 100 + ] + } + ], + "merge_queries": [], + "aggregations": [] + } + } + ], + "merge_queries": [], + "aggregations": [] +})", + default_namespace, kFieldNameName, joinNs, kFieldNameName, kFieldNameId), + Query(default_namespace) + .Where(kFieldNameName, CondEq, Query(joinNs).Select({kFieldNameName}).Where(kFieldNameId, CondSet, {1, 10, 100}))}, + {fmt::sprintf( + R"({ + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "gt", + "field": "%s", + "subquery": { + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [], + "merge_queries": [], + "aggregations": [ + { + "type": "avg", + "sort": [], + "fields": [ + "%s" + ] + } + ] + } + } + ], + "merge_queries": [], + "aggregations": [] +})", + default_namespace, kFieldNameId, joinNs, kFieldNameId), + Query(default_namespace).Where(kFieldNameId, CondGt, Query(joinNs).Aggregate(AggAvg, {kFieldNameId}))}, + {fmt::sprintf( + R"({ + "namespace": "%s", + "limit": -1, + "offset": 0, + "req_total": "disabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [ + { + "op": "and", + "cond": "gt", + "field": "%s", + "subquery": { + "namespace": "%s", + "limit": 0, + "offset": 0, + "req_total": "enabled", + "explain": false, + "type": "select", + "select_with_rank": false, + "select_filter": [], + "select_functions": [], + "sort": [], + "filters": [], + "merge_queries": [], + "aggregations": [] + } + } + ], + "merge_queries": [], + "aggregations": [] +})", + default_namespace, kFieldNameId, joinNs, kFieldNameId), + Query(default_namespace).Where(kFieldNameId, CondGt, Query(joinNs).ReqTotal())}}; for (const auto& [dsl, expected, direction] : cases) { if (std::holds_alternative(expected)) { const Query& q = std::get(expected); if (direction & GEN) { - EXPECT_EQ(q.GetJSON(), dsl); + reindexer::WrSerializer ser; + reindexer::prettyPrintJSON(q.GetJSON(), ser, 3); + EXPECT_EQ(ser.Slice(), dsl); } if (direction & PARSE) { Query parsed; try { - parsed.FromJSON(dsl); + const auto err = parsed.FromJSON(dsl); + ASSERT_TRUE(err.ok()) << err.what() << "\nDSL: " << dsl; } catch (const Error& err) { ADD_FAILURE() << "Unexpected error: " << err.what() << "\nDSL: " << dsl; continue; @@ -297,7 +611,8 @@ TEST_F(QueriesApi, DslGenerateParse) { const Error& expectedErr = std::get(expected); Query parsed; try { - parsed.FromJSON(dsl); + const auto err = parsed.FromJSON(dsl); + ASSERT_TRUE(err.ok()) << err.what(); ADD_FAILURE() << "Expected error: " << expectedErr.what() << "\nDSL: " << dsl; } catch (const Error& err) { EXPECT_EQ(err.what(), expectedErr.what()) << "\nDSL: " << dsl; @@ -352,7 +667,7 @@ TEST_F(QueriesApi, StrictModeTest) { const std::string kNotExistingField = "some_random_name123"; QueryResults qr; { - Query query = Query(testSimpleNs).Where(kNotExistingField, CondEmpty, {}); + Query query = Query(testSimpleNs).Where(kNotExistingField, CondEmpty, VariantArray{}); Error err = rt.reindexer->Select(query.Strict(StrictModeNames), qr); EXPECT_EQ(err.code(), errQueryExec); qr.Clear(); @@ -409,18 +724,16 @@ TEST_F(QueriesApi, SQLLeftJoinSerialize) { } { - Query qSql; std::string sqlQ = createQuery(tLeft, tRight, iLeft, iRight, c.first); - qSql.FromSQL(sqlQ); + Query qSql = Query::FromSQL(sqlQ); reindexer::WrSerializer wrSer; qSql.GetSQL(wrSer); ASSERT_EQ(sqlQ, std::string(wrSer.c_str())); } { - Query qSql; std::string sqlQ = createQuery(tRight, tLeft, iRight, iLeft, c.second); - qSql.FromSQL(sqlQ); + Query qSql = Query::FromSQL(sqlQ); ASSERT_EQ(q.GetJSON(), qSql.GetJSON()); reindexer::WrSerializer wrSer; qSql.GetSQL(wrSer); @@ -973,3 +1286,72 @@ TEST_F(QueriesApi, SortByFieldWithDifferentTypes) { sortByNsDifferentTypesImpl(nsName, Query{nsName}, ""); } + +TEST_F(QueriesApi, SerializeDeserialize) { + Query queries[]{ + Query(default_namespace).Where(Query(default_namespace), CondAny, {}), + Query(default_namespace).Where(kFieldNameUuidArr, CondRange, randHeterogeneousUuidArray(2, 2)), + Query(default_namespace) + .WhereComposite(kCompositeFieldUuidName, CondRange, + {VariantArray::Create(nilUuid(), RandString()), VariantArray::Create(randUuid(), RandString())}), + Query(default_namespace).Where(Query(default_namespace).Where(kFieldNameId, CondEq, 10), CondAny, {}), + Query(default_namespace).Not().Where(Query(default_namespace), CondEmpty, {}), + Query(default_namespace).Where(kFieldNameId, CondLt, Query(default_namespace).Aggregate(AggAvg, {kFieldNameId})), + Query(default_namespace) + .Where(kFieldNameGenre, CondSet, Query(joinNs).Select({kFieldNameGenre}).Where(kFieldNameId, CondSet, {10, 20, 30, 40})), + + Query(default_namespace).Where(Query(joinNs).Select({kFieldNameGenre}).Where(kFieldNameId, CondGt, 10), CondSet, {10, 20, 30, 40}), + Query(default_namespace) + .Where(Query(joinNs).Select({kFieldNameGenre}).Where(kFieldNameId, CondGt, 10).Offset(1), CondSet, {10, 20, 30, 40}), + Query(default_namespace) + .Where(Query(joinNs).Where(kFieldNameId, CondGt, 10).Aggregate(AggMax, {kFieldNameGenre}), CondRange, {48, 50}), + Query(default_namespace).Where(Query(joinNs).Where(kFieldNameId, CondGt, 10).ReqTotal(), CondGt, {50}), + Query(default_namespace) + .Debug(LogTrace) + .Where(kFieldNameGenre, CondEq, 5) + .Not() + .Where(Query(default_namespace).Where(kFieldNameGenre, CondEq, 5), CondAny, {}) + .Or() + .Where(kFieldNameGenre, CondSet, Query(joinNs).Select({kFieldNameGenre}).Where(kFieldNameId, CondSet, {10, 20, 30, 40})) + .Not() + .OpenBracket() + .Where(kFieldNameYear, CondRange, {2001, 2020}) + .Or() + .Where(kFieldNameName, CondLike, RandLikePattern()) + .Or() + .Where(Query(joinNs).Where(kFieldNameYear, CondEq, 2000 + rand() % 210), CondEmpty, {}) + .CloseBracket() + .Or() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .OpenBracket() + .Where(kFieldNameNumeric, CondLt, std::to_string(600)) + .Not() + .OpenBracket() + .Where(kFieldNamePackages, CondSet, RandIntVector(5, 10000, 50)) + .Where(kFieldNameGenre, CondLt, 6) + .Or() + .Where(kFieldNameId, CondLt, Query(default_namespace).Aggregate(AggAvg, {kFieldNameId})) + .CloseBracket() + .Not() + .Where(Query(joinNs).Where(kFieldNameId, CondGt, 10).Aggregate(AggMax, {kFieldNameGenre}), CondRange, {48, 50}) + .Or() + .Where(kFieldNameYear, CondEq, 10) + .CloseBracket(), + + Query(default_namespace) + .Where(kCompositeFieldIdTemp, CondEq, Query(default_namespace).Select({kCompositeFieldIdTemp}).Where(kFieldNameId, CondGt, 10)), + Query(default_namespace) + .Where(Query(default_namespace).Select({kCompositeFieldUuidName}).Where(kFieldNameId, CondGt, 10), CondRange, + {VariantArray::Create(nilUuid(), RandString()), VariantArray::Create(randUuid(), RandString())}), + Query(default_namespace) + .Where(Query(default_namespace).Select({kCompositeFieldAgeGenre}).Where(kFieldNameId, CondGt, 10).Limit(10), CondLe, + {Variant(VariantArray::Create(rand() % 50, rand() % 50))}), + }; + for (Query& q : queries) { + reindexer::WrSerializer wser; + q.Serialize(wser); + reindexer::Serializer rser(wser.Slice()); + const auto deserializedQuery = Query::Deserialize(rser); + EXPECT_EQ(q, deserializedQuery) << "Origin query:\n" << q.GetSQL() << "\nDeserialized query:\n" << deserializedQuery.GetSQL(); + } +} diff --git a/cpp_src/gtests/tests/unit/replication_master_master_test.cc b/cpp_src/gtests/tests/unit/replication_master_master_test.cc index b620b6109..d3d5c81ef 100644 --- a/cpp_src/gtests/tests/unit/replication_master_master_test.cc +++ b/cpp_src/gtests/tests/unit/replication_master_master_test.cc @@ -873,16 +873,16 @@ TEST_F(ReplicationSlaveSlaveApi, Node3ApplyWal) { } TEST_F(ReplicationSlaveSlaveApi, RestrictUpdates) { - // 1. create master node, - // 2. set max updates size 1024 * 5 - // 3. add 10000 rows - // 4. start inser thread - // 5. start slave node - // 6. wait sync - reindexer::fs::RmDirAll("/tmp/RestrictUpdates"); + // 1. create master node, + // 2. set max updates size 1024 * 5 + // 3. add 10000 rows + // 4. start inser thread + // 5. start slave node + // 6. wait sync + const std::string kBaseStoragePath = reindexer::fs::JoinPath(kBaseTestsetDbPath, "RestrictUpdates"); std::string upDsn = "cproto://127.0.0.1:7770/db"; ServerControl master; - master.InitServer(0, 7770, 7880, "/tmp/RestrictUpdates/master", "db", true, 1024 * 5); + master.InitServer(0, 7770, 7880, reindexer::fs::JoinPath(kBaseStoragePath, "master"), "db", true, 1024 * 5); master.Get()->MakeMaster(ReplicationConfigTest("master", "appMaster")); TestNamespace1 testns1(master, "ns1"); @@ -906,7 +906,7 @@ TEST_F(ReplicationSlaveSlaveApi, RestrictUpdates) { std::thread insertThread(ThreadAdd); ServerControl slave; - slave.InitServer(0, 7771, 7881, "/tmp/RestrictUpdates/slave", "db", true); + slave.InitServer(0, 7771, 7881, reindexer::fs::JoinPath(kBaseStoragePath, "slave"), "db", true); ReplicationConfigTest configSlave("slave", false, true, 0, upDsn, "slave"); slave.Get()->MakeSlave(0, configSlave); diff --git a/cpp_src/gtests/tests/unit/rpcclient_test.cc b/cpp_src/gtests/tests/unit/rpcclient_test.cc index 9ea0b80b9..468de912d 100644 --- a/cpp_src/gtests/tests/unit/rpcclient_test.cc +++ b/cpp_src/gtests/tests/unit/rpcclient_test.cc @@ -1046,3 +1046,72 @@ TEST_F(RPCClientTestApi, AggregationsFetching) { loop.run(); } + +TEST_F(RPCClientTestApi, SubQuery) { + using namespace reindexer::client; + using namespace reindexer::net::ev; + using reindexer::coroutine::wait_group; + using reindexer::coroutine::wait_group_guard; + + StartDefaultRealServer(); + dynamic_loop loop; + + loop.spawn([&loop, this]() noexcept { + const std::string kLeftNsName = "left_ns"; + const std::string kRightNsName = "right_ns"; + const std::string dsn = "cproto://" + kDefaultRPCServerAddr + "/db1"; + reindexer::client::ConnectOpts opts; + opts.CreateDBIfMissing(); + reindexer::client::ReindexerConfig cfg; + constexpr auto kFetchCount = 50; + constexpr auto kNsSize = kFetchCount * 3; + cfg.FetchAmount = kFetchCount; + CoroReindexer rx(cfg); + auto err = rx.Connect(dsn, loop, opts); + ASSERT_TRUE(err.ok()) << err.what(); + + CreateNamespace(rx, kLeftNsName); + CreateNamespace(rx, kRightNsName); + + auto upsertFn = [&rx](const std::string& nsName) { + for (size_t i = 0; i < kNsSize; ++i) { + auto item = rx.NewItem(nsName); + ASSERT_TRUE(item.Status().ok()) << nsName << " " << item.Status().what(); + + WrSerializer wrser; + JsonBuilder jsonBuilder(wrser, ObjType::TypeObject); + jsonBuilder.Put("id", i); + jsonBuilder.Put("value", "value_" + std::to_string(i)); + jsonBuilder.End(); + char* endp = nullptr; + auto err = item.Unsafe().FromJSON(wrser.Slice(), &endp); + ASSERT_TRUE(err.ok()) << nsName << " " << err.what(); + err = rx.Upsert(nsName, item); + ASSERT_TRUE(err.ok()) << nsName << " " << err.what(); + } + }; + + upsertFn(kLeftNsName); + upsertFn(kRightNsName); + + const auto kHalfSize = kNsSize / 2; + { + client::CoroQueryResults qr; + err = rx.Select(Query(kLeftNsName).Where("id", CondSet, Query(kRightNsName).Select({"id"}).Where("id", CondLt, kHalfSize)), qr); + ASSERT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(qr.Count(), kHalfSize); + } + { + const int limit = 10; + client::CoroQueryResults qr; + err = rx.Select( + Query(kLeftNsName).Where(Query(kRightNsName).Where("id", CondLt, kHalfSize).ReqTotal(), CondEq, {kHalfSize}).Limit(limit), + qr); + ASSERT_TRUE(err.ok()) << err.what(); + ASSERT_EQ(qr.Count(), limit); + } + rx.Stop(); + }); + + loop.run(); +} diff --git a/cpp_src/gtests/tests/unit/selector_plan_test.cc b/cpp_src/gtests/tests/unit/selector_plan_test.cc index 89a08333a..2f96be009 100644 --- a/cpp_src/gtests/tests/unit/selector_plan_test.cc +++ b/cpp_src/gtests/tests/unit/selector_plan_test.cc @@ -421,7 +421,7 @@ TEST_F(SelectorPlanTest, ConditionsMergeIntoEmptyCondition) { .Where("id", CondSet, {32, 33, 34}) .Where("id", CondEq, 310) .Where("id", CondSet, {35, 36, 37}) - .Where("value", CondAny, {}) + .Where("value", CondAny, VariantArray{}) .Explain(); QueryResults qr; err = rt.reindexer->Select(q, qr); @@ -438,8 +438,8 @@ TEST_F(SelectorPlanTest, ConditionsMergeIntoEmptyCondition) { const auto q = Query(nsName) .Where("id", CondEq, 39) .Where("id", CondSet, {32, 39, 34}) - .Where("id", CondSet, {}) - .Where("value", CondAny, {}) + .Where("id", CondSet, VariantArray{}) + .Where("value", CondAny, VariantArray{}) .Explain(); QueryResults qr; err = rt.reindexer->Select(q, qr); @@ -453,8 +453,12 @@ TEST_F(SelectorPlanTest, ConditionsMergeIntoEmptyCondition) { } { // Query with multiple empty sets - const auto q = - Query(nsName).Where("id", CondEq, 45).Where("id", CondSet, {}).Where("id", CondSet, {}).Where("value", CondAny, {}).Explain(); + const auto q = Query(nsName) + .Where("id", CondEq, 45) + .Where("id", CondSet, VariantArray{}) + .Where("id", CondSet, VariantArray{}) + .Where("value", CondAny, VariantArray{}) + .Explain(); QueryResults qr; err = rt.reindexer->Select(q, qr); ASSERT_TRUE(err.ok()) << err.what(); diff --git a/cpp_src/gtests/tests/unit/sql_parser_test.cc b/cpp_src/gtests/tests/unit/sql_parser_test.cc index 9d48c118a..aa4a51d3b 100644 --- a/cpp_src/gtests/tests/unit/sql_parser_test.cc +++ b/cpp_src/gtests/tests/unit/sql_parser_test.cc @@ -3,12 +3,10 @@ #include "core/query/query.h" #include "core/query/sql/sqlparser.h" -struct SQLParserTests : public ::testing::TestWithParam { - reindexer::Query query; -}; +struct SQLParserTests : public ::testing::TestWithParam {}; // --gtest_filter=*/SQLParserTests.NumberInDoubleQuotesParsedCorrectly/* -TEST_P(SQLParserTests, NumberInDoubleQuotesParsedCorrectly) { EXPECT_NO_THROW(reindexer::SQLParser(query).Parse(GetParam())); } +TEST_P(SQLParserTests, NumberInDoubleQuotesParsedCorrectly) { EXPECT_NO_THROW(auto q = reindexer::SQLParser::Parse(GetParam())); } // --gtest_filter=Update/SQLParserTests.NumberInDoubleQuotesParsedCorrectly/* INSTANTIATE_TEST_SUITE_P(Update, SQLParserTests, @@ -63,14 +61,12 @@ INSTANTIATE_TEST_SUITE_P(Delete, SQLParserTests, "DELETE FROM ns WHERE \"123\" = 123 AND \"abc123\" = 'some_value' AND \"123abc123\" = 123", "DELETE FROM ns WHERE \"123\" = 123 AND \"abc123\" = \"123abc123\" AND \"123abc123\" = 123")); -struct SQLParserWhere : public ::testing::TestWithParam> { - reindexer::Query query; -}; +struct SQLParserWhere : public ::testing::TestWithParam> {}; TEST_P(SQLParserWhere, CheckWhereError) { auto [sql, errString] = GetParam(); try { - reindexer::SQLParser(query).Parse(sql); + auto q = reindexer::SQLParser::Parse(sql); FAIL() << "[" << sql << "] is parsed"; } catch (reindexer::Error& err) { EXPECT_EQ(err.what(), errString); diff --git a/cpp_src/gtests/tests_data/MsgPack/msg.json b/cpp_src/gtests/tests_data/MsgPack/msg.json index af8f4d5ff..2dc741879 100644 --- a/cpp_src/gtests/tests_data/MsgPack/msg.json +++ b/cpp_src/gtests/tests_data/MsgPack/msg.json @@ -119,13 +119,13 @@ "1": { "user": { "id": 19, - "price": 424, - "oldPrice": 424 + "price": 424.0, + "oldPrice": 424.0 }, "guest": { "id": 20, - "price": 424, - "oldPrice": 424 + "price": 424.0, + "oldPrice": 424.0 } } }, @@ -200,13 +200,13 @@ "1": { "user": { "id": 29, - "price": 623, - "oldPrice": 623 + "price": 623.0, + "oldPrice": 623.0 }, "guest": { "id": 30, - "price": 623, - "oldPrice": 623 + "price": 623.0, + "oldPrice": 623.0 } } }, @@ -416,13 +416,13 @@ "1": { "user": { "id": 55, - "price": 371, - "oldPrice": 371 + "price": 371.0, + "oldPrice": 371.0 }, "guest": { "id": 56, - "price": 371, - "oldPrice": 371 + "price": 371.0, + "oldPrice": 371.0 } } }, @@ -470,13 +470,13 @@ "1": { "user": { "id": 23, - "price": 371, - "oldPrice": 371 + "price": 371.0, + "oldPrice": 371.0 }, "guest": { "id": 24, - "price": 371, - "oldPrice": 371 + "price": 371.0, + "oldPrice": 371.0 } } }, @@ -630,4 +630,5 @@ "title": "12" } ] -} \ No newline at end of file +} + diff --git a/cpp_src/readme.md b/cpp_src/readme.md index 05c6e0cfb..b496cca9e 100644 --- a/cpp_src/readme.md +++ b/cpp_src/readme.md @@ -46,7 +46,7 @@ yum update yum install reindexer-server ``` -Available distros: `centos-7`, `fedora-36`, `fedora-37`, `redos-7` +Available distros: `centos-7`, `fedora-38`, `fedora-39`, `redos-7` ### Ubuntu/Debian diff --git a/cpp_src/replicator/replicator.cc b/cpp_src/replicator/replicator.cc index b44862777..1c8e80200 100644 --- a/cpp_src/replicator/replicator.cc +++ b/cpp_src/replicator/replicator.cc @@ -5,7 +5,7 @@ #include "core/itemimpl.h" #include "core/namespace/namespaceimpl.h" #include "core/namespacedef.h" -#include "core/reindexerimpl.h" +#include "core/reindexer_impl/reindexerimpl.h" #include "tools/logger.h" #include "tools/stringstools.h" #include "walrecord.h" @@ -581,7 +581,7 @@ Error Replicator::syncNamespaceForced(const NamespaceDef &ns, std::string_view r // Make query to complete master's namespace data client::QueryResults qr(kResultsWithPayloadTypes | kResultsCJson | kResultsWithItemID | kResultsWithRaw); - if (err.ok()) err = master_->Select(Query(ns.name).Where("#lsn", CondAny, {}), qr); + if (err.ok()) err = master_->Select(Query(ns.name).Where("#lsn", CondAny, VariantArray{}), qr); if (err.ok()) err = tmpNs->ReplaceTagsMatcher(qr.getTagsMatcher(0), dummyCtx_); if (err.ok()) { err = applyWAL(tmpNs, qr, &ns); @@ -682,8 +682,7 @@ Error Replicator::applyTxWALRecord(LSNPair LSNs, std::string_view nsName, Namesp // Update query case WalUpdateQuery: { QueryResults result; - Query q; - q.FromSQL(rec.data); + Query q = Query::FromSQL(rec.data); std::lock_guard lck(syncMtx_); Transaction &tx = transactions_[slaveNs.get()]; if (tx.IsFree()) return Error(errLogic, "[repl:%s]:%d Transaction was not initiated.", nsName, config_.serverId); @@ -705,6 +704,20 @@ Error Replicator::applyTxWALRecord(LSNPair LSNs, std::string_view nsName, Namesp slaveNs->CommitTransaction(tx, res, rdxContext); tx = Transaction{}; } break; + case WalTagsMatcher: { + std::lock_guard lck(syncMtx_); + Transaction &tx = transactions_[slaveNs.get()]; + if (tx.IsFree()) return Error(errLogic, "[repl:%s]:%d Transaction was not initiated.", nsName, config_.serverId); + + TagsMatcher tm; + Serializer ser(rec.data.data(), rec.data.size()); + const auto version = ser.GetVarint(); + const auto stateToken = ser.GetVarint(); + tm.deserialize(ser, version, stateToken); + logPrintf(LogInfo, "[repl:%s]:%d Got new tagsmatcher replicated via tx: { state_token: %08X, version: %d }", nsName, + config_.serverId, stateToken, version); + tx.SetTagsMatcher(std::move(tm)); + } break; case WalEmpty: case WalReplState: case WalItemUpdate: @@ -718,6 +731,9 @@ Error Replicator::applyTxWALRecord(LSNPair LSNs, std::string_view nsName, Namesp case WalForceSync: case WalSetSchema: case WalWALSync: + case WalResetLocalWal: + case WalRawItem: + case WalShallowItem: return Error(errLogic, "Unexpected for transaction WAL rec type %d\n", int(rec.type)); } return {}; @@ -794,8 +810,7 @@ Error Replicator::applyWALRecord(LSNPair LSNs, std::string_view nsName, Namespac logPrintf(LogTrace, "[repl:%s]:%d WalUpdateQuery", nsName, config_.serverId); checkNoOpenedTransaction(nsName, slaveNs); QueryResults result; - Query q; - q.FromSQL(rec.data); + Query q = Query::FromSQL(rec.data); switch (q.type_) { case QueryDelete: slaveNs->Delete(q, result, rdxContext); @@ -850,10 +865,24 @@ Error Replicator::applyWALRecord(LSNPair LSNs, std::string_view nsName, Namespac slaveNs->SetSchema(rec.data, rdxContext); stat.schemasSet++; break; + case WalTagsMatcher: { + checkNoOpenedTransaction(nsName, slaveNs); + TagsMatcher tm; + Serializer ser(rec.data.data(), rec.data.size()); + const auto version = ser.GetVarint(); + const auto stateToken = ser.GetVarint(); + tm.deserialize(ser, version, stateToken); + logPrintf(LogInfo, "[repl:%s]:%d Got new tagsmatcher replicated via single record: { state_token: %08X, version: %d }", nsName, + config_.serverId, stateToken, version); + slaveNs->SetTagsMatcher(std::move(tm), rdxContext); + } break; case WalEmpty: case WalItemUpdate: case WalInitTransaction: case WalCommitTransaction: + case WalResetLocalWal: + case WalRawItem: + case WalShallowItem: return Error(errLogic, "Unexpected WAL rec type %d\n", int(rec.type)); } return err; @@ -982,6 +1011,24 @@ Error Replicator::syncMetaForced(Namespace::Ptr &slaveNs, std::string_view nsNam // Callback from WAL updates pusher void Replicator::OnWALUpdate(LSNPair LSNs, std::string_view nsName, const WALRecord &wrec) { + try { + onWALUpdateImpl(LSNs, nsName, wrec); + } catch (Error &e) { + logPrintf(LogError, "[repl:%s]:%d Exception on WAL update: %s", nsName, config_.serverId, e.what()); + assertrx_dbg(false); + resync_.send(); + } catch (std::exception &e) { + logPrintf(LogError, "[repl:%s]:%d Exception on WAL update (std::exception): %s", nsName, config_.serverId, e.what()); + assertrx_dbg(false); + resync_.send(); + } catch (...) { + logPrintf(LogError, "[repl:%s]:%d Exception on WAL update: ", nsName, config_.serverId); + assertrx_dbg(false); + resync_.send(); + } +} + +void Replicator::onWALUpdateImpl(LSNPair LSNs, std::string_view nsName, const WALRecord &wrec) { auto sId = LSNs.originLSN_.Server(); if (sId != 0) { // sId = 0 for configurations without specifying a server id if (sId == config_.serverId) { @@ -1201,6 +1248,7 @@ bool Replicator::SyncQueue::Pop(std::string_view nsName, const std::unique_lock< // Pop() must be called under top level replicator's sync mutex assertrx(replicatorLock.owns_lock()); assertrx(replicatorLock.mutex() == &replicatorMtx_); + (void)replicatorMtx_; (void)replicatorLock; auto cnt = queue_.erase(nsName); if (cnt) { diff --git a/cpp_src/replicator/replicator.h b/cpp_src/replicator/replicator.h index 0a2c9b4bf..5a3949a9d 100644 --- a/cpp_src/replicator/replicator.h +++ b/cpp_src/replicator/replicator.h @@ -94,7 +94,8 @@ class Replicator : public IUpdatesObserver { // Push update to the queue to apply it later void pushPendingUpdate(LSNPair LSNs, std::string_view nsName, const WALRecord &wrec); - void OnWALUpdate(LSNPair LSNs, std::string_view nsName, const WALRecord &walRec) override final; + void OnWALUpdate(LSNPair LSNs, std::string_view nsName, const WALRecord &wrec) override final; + void onWALUpdateImpl(LSNPair LSNs, std::string_view nsName, const WALRecord &wrec); void OnUpdatesLost(std::string_view nsName) override final; void OnConnectionState(const Error &err) override final; diff --git a/cpp_src/replicator/walrecord.cc b/cpp_src/replicator/walrecord.cc index e97d56757..b2222f6ec 100644 --- a/cpp_src/replicator/walrecord.cc +++ b/cpp_src/replicator/walrecord.cc @@ -19,8 +19,9 @@ void WALRecord::Pack(WrSerializer &ser) const { ser.PutVarUint(inTransaction ? (type | TxBit) : type); switch (type) { case WalItemUpdate: + case WalShallowItem: ser.PutUInt32(id); - break; + return; case WalUpdateQuery: case WalIndexAdd: case WalIndexDrop: @@ -30,29 +31,32 @@ void WALRecord::Pack(WrSerializer &ser) const { case WalForceSync: case WalWALSync: case WalSetSchema: + case WalTagsMatcher: ser.PutVString(data); - break; + return; case WalPutMeta: ser.PutVString(putMeta.key); ser.PutVString(putMeta.value); - break; + return; case WalItemModify: ser.PutVString(itemModify.itemCJson); ser.PutVarUint(itemModify.modifyMode); ser.PutVarUint(itemModify.tmVersion); - break; + return; + case WalRawItem: + ser.PutUInt32(rawItem.id); + ser.PutVString(rawItem.itemCJson); + return; case WalEmpty: - ser.Reset(); - break; case WalNamespaceAdd: case WalNamespaceDrop: case WalInitTransaction: case WalCommitTransaction: - break; - default: - fprintf(stderr, "Unexpected WAL rec type %d\n", int(type)); - std::abort(); + case WalResetLocalWal: + return; } + fprintf(stderr, "Unexpected WAL rec type %d\n", int(type)); + std::abort(); } WALRecord::WALRecord(span packed) { @@ -71,8 +75,9 @@ WALRecord::WALRecord(span packed) { } switch (type) { case WalItemUpdate: + case WalShallowItem: id = ser.GetUInt32(); - break; + return; case WalUpdateQuery: case WalIndexAdd: case WalIndexDrop: @@ -82,27 +87,31 @@ WALRecord::WALRecord(span packed) { case WalForceSync: case WalWALSync: case WalSetSchema: + case WalTagsMatcher: data = ser.GetVString(); - break; + return; case WalPutMeta: putMeta.key = ser.GetVString(); putMeta.value = ser.GetVString(); - break; + return; case WalItemModify: itemModify.itemCJson = ser.GetVString(); itemModify.modifyMode = ser.GetVarUint(); itemModify.tmVersion = ser.GetVarUint(); - break; + return; + case WalRawItem: + rawItem.id = ser.GetUInt32(); + rawItem.itemCJson = ser.GetVString(); + return; case WalEmpty: case WalNamespaceAdd: case WalNamespaceDrop: case WalInitTransaction: case WalCommitTransaction: - break; - default: - logPrintf(LogWarning, "Unexpected WAL rec type %d\n", int(type)); - break; + case WalResetLocalWal: + return; } + logPrintf(LogError, "Unexpected WAL rec type %d\n", int(type)); } static std::string_view wrecType2Str(WALRecType t) { @@ -142,9 +151,16 @@ static std::string_view wrecType2Str(WALRecType t) { return "WalWALSync"sv; case WalSetSchema: return "WalSetSchema"sv; - default: - return ""sv; + case WalRawItem: + return "WalRawItem"sv; + case WalShallowItem: + return "WalShallowItem"sv; + case WalTagsMatcher: + return "WalTagsMatcher"sv; + case WalResetLocalWal: + return "WalResetLocalWal"sv; } + return ""sv; } WrSerializer &WALRecord::Dump(WrSerializer &ser, const std::function &cjsonViewer) const { @@ -156,10 +172,13 @@ WrSerializer &WALRecord::Dump(WrSerializer &ser, const std::function &cjsonViewer) const { @@ -191,8 +210,10 @@ void WALRecord::GetJSON(JsonBuilder &jb, const std::function(reinterpret_cast(data.data()), data.size())) {} diff --git a/cpp_src/replicator/walrecord.h b/cpp_src/replicator/walrecord.h index 1b6a0e9e0..bb25452eb 100644 --- a/cpp_src/replicator/walrecord.h +++ b/cpp_src/replicator/walrecord.h @@ -30,6 +30,10 @@ enum WALRecType { WalForceSync = 14, WalSetSchema = 15, WalWALSync = 16, + WalTagsMatcher = 17, + WalResetLocalWal = 18, + WalRawItem = 19, + WalShallowItem = 20, }; class WrSerializer; @@ -57,8 +61,8 @@ struct WALRecord { explicit WALRecord(WALRecType _type, std::string_view key, std::string_view value) : type(_type), putMeta{key, value} {} explicit WALRecord(WALRecType _type, std::string_view cjson, int tmVersion, int modifyMode, bool inTx = false) : type(_type), itemModify{cjson, tmVersion, modifyMode}, inTransaction(inTx) {} - WrSerializer &Dump(WrSerializer &ser, const std::function& cjsonViewer) const; - void GetJSON(JsonBuilder &jb, const std::function& cjsonViewer) const; + WrSerializer &Dump(WrSerializer &ser, const std::function &cjsonViewer) const; + void GetJSON(JsonBuilder &jb, const std::function &cjsonViewer) const; void Pack(WrSerializer &ser) const; SharedWALRecord GetShared(int64_t lsn, int64_t upstreamLSN, std::string_view nsName) const; @@ -75,6 +79,10 @@ struct WALRecord { std::string_view key; std::string_view value; } putMeta; + struct { + IdType id; + std::string_view itemCJson; + } rawItem; }; bool inTransaction = false; mutable SharedWALRecord shared_; diff --git a/cpp_src/replicator/walselecter.cc b/cpp_src/replicator/walselecter.cc index 23da38c5c..4d6cd1c48 100644 --- a/cpp_src/replicator/walselecter.cc +++ b/cpp_src/replicator/walselecter.cc @@ -22,12 +22,12 @@ void WALSelecter::operator()(QueryResults &result, SelectCtx ¶ms) { throw Error(errLogic, "Query to WAL should contain only 1 condition '#lsn > number'"); } - result.addNSContext(ns_->payloadType_, ns_->tagsMatcher_, FieldsSet(ns_->tagsMatcher_, q.selectFilter_), ns_->schema_); + result.addNSContext(ns_->payloadType_, ns_->tagsMatcher_, FieldsSet(ns_->tagsMatcher_, q.SelectFilters()), ns_->schema_); int lsnIdx = -1; int versionIdx = -1; - for (size_t i = 0; i < q.entries.Size(); ++i) { - q.entries.InvokeAppropriate( + for (size_t i = 0; i < q.Entries().Size(); ++i) { + q.Entries().InvokeAppropriate( i, [&lsnIdx, &versionIdx, i](const QueryEntry &qe) { if ("#lsn"sv == qe.FieldName()) { @@ -40,8 +40,8 @@ void WALSelecter::operator()(QueryResults &result, SelectCtx ¶ms) { }, [&q](const auto &) { throw Error(errLogic, "Unexpected WAL select query: %s", q.GetSQL()); }); } - auto slaveVersion = versionIdx < 0 ? SemVersion() : SemVersion(q.entries.Get(versionIdx).Values()[0].As()); - auto &lsnEntry = q.entries.Get(lsnIdx); + auto slaveVersion = versionIdx < 0 ? SemVersion() : SemVersion(q.Entries().Get(versionIdx).Values()[0].As()); + auto &lsnEntry = q.Entries().Get(lsnIdx); if (lsnEntry.Values().size() == 1 && lsnEntry.Condition() == CondGt) { lsn_t fromLSN = lsn_t(std::min(lsnEntry.Values()[0].As(), std::numeric_limits::max() - 1)); if (fromLSN.Server() != ns_->serverId_) @@ -72,7 +72,7 @@ void WALSelecter::operator()(QueryResults &result, SelectCtx ¶ms) { if (versionIdx < 0) { break; } - if (q.entries.Get(versionIdx).Condition() != CondEq || slaveVersion < kMinUnknownReplSupportRxVersion) { + if (q.Entries().Get(versionIdx).Condition() != CondEq || slaveVersion < kMinUnknownReplSupportRxVersion) { break; } // fall-through @@ -106,6 +106,10 @@ void WALSelecter::operator()(QueryResults &result, SelectCtx ¶ms) { case WalNamespaceRename: case WalForceSync: case WalWALSync: + case WalRawItem: + case WalShallowItem: + case WalTagsMatcher: + case WalResetLocalWal: std::abort(); } } diff --git a/cpp_src/server/CMakeLists.txt b/cpp_src/server/CMakeLists.txt index 3d94922be..5a11d10db 100644 --- a/cpp_src/server/CMakeLists.txt +++ b/cpp_src/server/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.0) project(reindexer_server_library) set (SWAGGER_VERSION "2.x") -set (GH_FACE_VERSION "3.20.1") +set (GH_FACE_VERSION "3.21.0") set (GH_FACE_TAG "v${GH_FACE_VERSION}") set (TARGET reindexer_server_library) set (SERVER_LIB_DIR ${PROJECT_BINARY_DIR} PARENT_SCOPE) diff --git a/cpp_src/server/contrib/server.md b/cpp_src/server/contrib/server.md index df5c094f5..adc37f0cf 100644 --- a/cpp_src/server/contrib/server.md +++ b/cpp_src/server/contrib/server.md @@ -2246,6 +2246,7 @@ If contains 'filters' then cannot contain 'cond', 'field' and 'value'. If not co |Name|Description|Schema| |---|---|---| +|**always**
*optional*|Boolean constant|boolean| |**cond**
*optional*|Condition operator|enum (EQ, GT, GE, LE, LT, SET, ALLSET, EMPTY, RANGE, LIKE, DWITHIN)| |**equal_positions**
*optional*|Array of array fields to be searched with equal array indexes|< [EqualPositionDef](#equalpositiondef) > array| |**field**
*optional*|Field json path or index name for filter|string| @@ -2254,6 +2255,7 @@ If contains 'filters' then cannot contain 'cond', 'field' and 'value'. If not co |**join_query**
*optional*||[JoinedDef](#joineddef)| |**op**
*optional*|Logic operator|enum (AND, OR, NOT)| |**second_field**
*optional*|Second field json path or index name for filter by two fields|string| +|**subquery**
*optional*|Subquery to compare its result|[Query](#query)| |**value**
*optional*|Value of filter. Single integer or string for EQ, GT, GE, LE, LT condition, array of 2 elements for RANGE condition, variable len array for SET and ALLSET conditions, or something like that: '[[1, -3.5],5.0]' for DWITHIN|object| @@ -2284,7 +2286,7 @@ Fulltext Index configuration |**max_total_areas_to_cache**
*optional*|Max total number of highlighted areas in ft result, when result still remains cacheable. '-1' means unlimited
**Maximum value** : `1000000000`|number| |**max_typo_len**
*optional*|Maximum word length for building and matching variants with typos.
**Minimum value** : `0`
**Maximum value** : `100`|integer| |**max_typos**
*optional*|Maximum possible typos in word. 0: typos is disabled, words with typos will not match. N: words with N possible typos will match. It is not recommended to set more than 2 possible typo -It will seriously increase RAM usage, and decrease search speed
**Minimum value** : `0`
**Maximum value** : `4`|integer| -|**merge_limit**
*optional*|Maximum documents count which will be processed in merge query results. Increasing this value may refine ranking of queries with high frequency words, but will decrease search speed
**Minimum value** : `0`
**Maximum value** : `65535`|integer| +|**merge_limit**
*optional*|Maximum documents count which will be processed in merge query results. Increasing this value may refine ranking of queries with high frequency words, but will decrease search speed
**Minimum value** : `0`
**Maximum value** : `65000`|integer| |**min_relevancy**
*optional*|Minimum rank of found documents. 0: all found documents will be returned 1: only documents with relevancy >= 100% will be returned
**Default** : `0.05`
**Minimum value** : `0`
**Maximum value** : `1`|number (float)| |**optimization**
*optional*|Optimize the index by memory or by cpu
**Default** : `"Memory"`|enum (Memory, CPU)| |**partial_match_decrease**
*optional*|Decrease of relevancy in case of partial match by value: partial_match_decrease * (non matched symbols) / (matched symbols)
**Minimum value** : `0`
**Maximum value** : `100`|integer| @@ -2793,6 +2795,7 @@ Performance statistics per each query |**master_dsn**
*optional*|DSN to master. Only cproto schema is supported|string| |**namespaces**
*optional*|List of namespaces for replication. If emply, all namespaces. All replicated namespaces will become read only for slave|< string > array| |**role**
*optional*|Replication role|enum (none, slave, master)| +|**server_id**
*optional*|Node identifier. Should be unique for each node in the replicated cluster (non-unique IDs are also allowed, but may lead to the inconsistency in some cases
**Maximum value** : `999`|integer| |**timeout_sec**
*optional*|Network timeout for communication with master, in seconds|integer| diff --git a/cpp_src/server/contrib/server.yml b/cpp_src/server/contrib/server.yml index 2df0c33cd..ea8e77e5a 100644 --- a/cpp_src/server/contrib/server.yml +++ b/cpp_src/server/contrib/server.yml @@ -2560,6 +2560,12 @@ definitions: second_field: description: "Second field json path or index name for filter by two fields" type: string + subquery: + description: "Subquery to compare its result" + $ref: "#/definitions/Query" + always: + description: "Boolean constant" + type: boolean equal_positions: type: array description: "Array of array fields to be searched with equal array indexes" @@ -2738,8 +2744,8 @@ definitions: type: integer default: 20000 minimum: 0 - maximum: 65535 - description: "Maximum documents count which will be processed in merge query results. Increasing this value may refine ranking of queries with high frequency words, but will decrease search speed" + maximum: 65000 + description: "Maximum documents count which will be processed in merge query results. Increasing this value may refine ranking of queries with high frequency words, but will decrease search speed" extra_word_symbols: type: string default: "-/+" @@ -3984,7 +3990,14 @@ definitions: description: "Enable network traffic compression" cluster_id: type: integer + default: 2 description: "Cluser ID - must be same for client and for master" + server_id: + type: integer + default: 0 + minimun: 0 + maximum: 999 + description: "Node identifier. Should be unique for each node in the replicated cluster (non-unique IDs are also allowed, but may lead to the inconsistency in some cases" force_sync_on_logic_error: type: boolean description: "force resync on logic error conditions" diff --git a/cpp_src/server/grpc/reindexerservice.cc b/cpp_src/server/grpc/reindexerservice.cc index 22085eedd..c5d808c5f 100644 --- a/cpp_src/server/grpc/reindexerservice.cc +++ b/cpp_src/server/grpc/reindexerservice.cc @@ -943,9 +943,8 @@ ::grpc::Status ReindexerService::RollbackTransaction(::grpc::ServerContext*, con Error ReindexerService::execSqlQueryByType(QueryResults& res, const SelectSqlRequest& request) { try { - reindexer::Query q; reindexer_server::UserRole requiredRole; - q.FromSQL(request.sql()); + reindexer::Query q = reindexer::Query::FromSQL(request.sql()); switch (q.Type()) { case QuerySelect: { requiredRole = reindexer_server::kRoleDataRead; diff --git a/cpp_src/server/httpserver.cc b/cpp_src/server/httpserver.cc index 65bd6dc2f..87cd16189 100644 --- a/cpp_src/server/httpserver.cc +++ b/cpp_src/server/httpserver.cc @@ -9,8 +9,6 @@ #include "core/cjson/msgpackdecoder.h" #include "core/cjson/protobufbuilder.h" #include "core/cjson/protobufschemabuilder.h" -#include "core/itemimpl.h" -#include "core/namespace/namespace.h" #include "core/queryresults/tableviewbuilder.h" #include "core/schema.h" #include "core/type_consts.h" @@ -24,12 +22,12 @@ #include "resources_wrapper.h" #include "statscollect/istatswatcher.h" #include "statscollect/prometheus.h" -#include "tools/alloc_ext/je_malloc_extension.h" #include "tools/alloc_ext/tc_malloc_extension.h" +#include "tools/flagguard.h" #include "tools/fsops.h" -#include "tools/jsontools.h" #include "tools/serializer.h" #include "tools/stringstools.h" +#include "vendor/sort/pdqsort.hpp" #include "outputparameters.h" @@ -51,8 +49,7 @@ HTTPServer::HTTPServer(DBManager &dbMgr, LoggerWrapper &logger, const ServerConf startTs_(std::chrono::system_clock::now()) {} Error HTTPServer::execSqlQueryByType(std::string_view sqlQuery, reindexer::QueryResults &res, http::Context &ctx) { - reindexer::Query q; - q.FromSQL(sqlQuery); + const auto q = reindexer::Query::FromSQL(sqlQuery); switch (q.Type()) { case QuerySelect: return getDB(ctx).Select(q, res); @@ -226,11 +223,9 @@ int HTTPServer::GetDatabases(http::Context &ctx) { } if (sortDirection) { - std::sort(dbs.begin(), dbs.end(), [sortDirection](const std::string &lhs, const std::string &rhs) { - if (sortDirection > 0) - return collateCompare(lhs, rhs, SortingPrioritiesTable()) < 0; - else - return collateCompare(lhs, rhs, SortingPrioritiesTable()) > 0; + boost::sort::pdqsort(dbs.begin(), dbs.end(), [sortDirection](const std::string &lhs, const std::string &rhs) { + return (sortDirection > 0) ? (collateCompare(lhs, rhs, SortingPrioritiesTable()) < 0) + : (collateCompare(lhs, rhs, SortingPrioritiesTable()) > 0); }); } @@ -320,11 +315,9 @@ int HTTPServer::GetNamespaces(http::Context &ctx) { } if (sortDirection) { - std::sort(nsDefs.begin(), nsDefs.end(), [sortDirection](const NamespaceDef &lhs, const NamespaceDef &rhs) { - if (sortDirection > 0) - return collateCompare(lhs.name, rhs.name, SortingPrioritiesTable()) < 0; - else - return collateCompare(lhs.name, rhs.name, SortingPrioritiesTable()) > 0; + boost::sort::pdqsort(nsDefs.begin(), nsDefs.end(), [sortDirection](const NamespaceDef &lhs, const NamespaceDef &rhs) { + return (sortDirection > 0) ? (collateCompare(lhs.name, rhs.name, SortingPrioritiesTable()) < 0) + : (collateCompare(lhs.name, rhs.name, SortingPrioritiesTable()) > 0); }); } @@ -483,9 +476,7 @@ int HTTPServer::GetItems(http::Context &ctx) { querySer << " OFFSET " << prepareOffset(offsetParam); } - reindexer::Query q; - - q.FromSQL(querySer.Slice()); + reindexer::Query q = Query::FromSQL(querySer.Slice()); if (ctx.request->params.Get("format") != "csv-file"sv) { q.ReqTotal(); } @@ -543,9 +534,9 @@ int HTTPServer::GetMetaList(http::Context &ctx) { return jsonStatus(ctx, http::HttpStatus(err)); } if (sortDirection == Asc) { - std::sort(keys.begin(), keys.end()); + boost::sort::pdqsort(keys.begin(), keys.end()); } else if (sortDirection == Desc) { - std::sort(keys.begin(), keys.end(), std::greater()); + boost::sort::pdqsort(keys.begin(), keys.end(), std::greater()); } auto keysIt = keys.begin(); auto keysEnd = keys.end(); @@ -1638,10 +1629,10 @@ unsigned HTTPServer::prepareOffset(std::string_view offsetParam, int offsetDefau int HTTPServer::modifyQueryTxImpl(http::Context &ctx, const std::string &dbName, std::string_view txId, Query &q) { reindexer::QueryResults res; auto tx = getTx(dbName, txId); - if (!q.mergeQueries_.empty()) { + if (!q.GetMergeQueries().empty()) { return status(ctx, http::HttpStatus(http::StatusBadRequest, "Merged subqueries are not allowed inside TX")); } - if (!q.joinQueries_.empty()) { + if (!q.GetJoinQueries().empty()) { return status(ctx, http::HttpStatus(http::StatusBadRequest, "Joined subqueries are not allowed inside TX")); } tx->Modify(std::move(q)); @@ -1890,8 +1881,7 @@ int HTTPServer::GetSQLQueryTx(http::Context &ctx) { } try { - Query q; - q.FromSQL(sqlQuery); + auto q = Query::FromSQL(sqlQuery); switch (q.type_) { case QueryDelete: case QueryUpdate: diff --git a/cpp_src/server/rpcserver.cc b/cpp_src/server/rpcserver.cc index c729cb065..b563e6afa 100644 --- a/cpp_src/server/rpcserver.cc +++ b/cpp_src/server/rpcserver.cc @@ -7,6 +7,7 @@ #include "net/cproto/cproto.h" #include "net/cproto/serverconnection.h" #include "reindexer_version.h" +#include "tools/catch_and_return.h" #include "vendor/msgpack/msgpack.h" namespace reindexer_server { @@ -175,8 +176,10 @@ void RPCServer::OnClose(cproto::Context &ctx, const Error &err) { if (qrId.main >= 0) { try { qrWatcher_.FreeQueryResults(qrId, false); + // NOLINTBEGIN(bugprone-empty-catch) } catch (...) { } + // NOLINTEND(bugprone-empty-catch) } } } @@ -196,10 +199,9 @@ void RPCServer::OnResponse(cproto::Context &ctx) { } } -Error RPCServer::execSqlQueryByType(std::string_view sqlQuery, QueryResults &res, cproto::Context &ctx) { +Error RPCServer::execSqlQueryByType(std::string_view sqlQuery, QueryResults &res, cproto::Context &ctx) noexcept { try { - reindexer::Query q; - q.FromSQL(sqlQuery); + const auto q = Query::FromSQL(sqlQuery); switch (q.Type()) { case QuerySelect: return getDB(ctx, kRoleDataRead).Select(q, res); @@ -211,9 +213,8 @@ Error RPCServer::execSqlQueryByType(std::string_view sqlQuery, QueryResults &res return getDB(ctx, kRoleDBAdmin).TruncateNamespace(q.NsName()); } return Error(errParams, "unknown query type %d", q.Type()); - } catch (Error &e) { - return e; } + CATCH_AND_RETURN; } void RPCServer::Logger(cproto::Context &ctx, const Error &err, const cproto::Args &ret) { @@ -391,36 +392,32 @@ Error RPCServer::AddTxItem(cproto::Context &ctx, int format, p_string itemData, return err; } -Error RPCServer::DeleteQueryTx(cproto::Context &ctx, p_string queryBin, int64_t txID) { - auto db = getDB(ctx, kRoleDataWrite); - - Transaction &tr = getTx(ctx, txID); - Query query; - Serializer ser(queryBin.data(), queryBin.size()); +Error RPCServer::DeleteQueryTx(cproto::Context &ctx, p_string queryBin, int64_t txID) noexcept { try { - query.Deserialize(ser); - } catch (Error &err) { - return err; + auto db = getDB(ctx, kRoleDataWrite); + + Transaction &tr = getTx(ctx, txID); + Serializer ser(queryBin.data(), queryBin.size()); + Query query = Query::Deserialize(ser); + query.type_ = QueryDelete; + tr.Modify(std::move(query)); + return errOK; } - query.type_ = QueryDelete; - tr.Modify(std::move(query)); - return errOK; + CATCH_AND_RETURN; } -Error RPCServer::UpdateQueryTx(cproto::Context &ctx, p_string queryBin, int64_t txID) { - auto db = getDB(ctx, kRoleDataWrite); - - Transaction &tr = getTx(ctx, txID); - Query query; - Serializer ser(queryBin.data(), queryBin.size()); +Error RPCServer::UpdateQueryTx(cproto::Context &ctx, p_string queryBin, int64_t txID) noexcept { try { - query.Deserialize(ser); - } catch (Error &err) { - return err; + auto db = getDB(ctx, kRoleDataWrite); + + Transaction &tr = getTx(ctx, txID); + Serializer ser(queryBin.data(), queryBin.size()); + Query query = Query::Deserialize(ser); + query.type_ = QueryUpdate; + tr.Modify(std::move(query)); + return errOK; } - query.type_ = QueryUpdate; - tr.Modify(std::move(query)); - return errOK; + CATCH_AND_RETURN; } Error RPCServer::CommitTx(cproto::Context &ctx, int64_t txId, std::optional flagsOpts) { @@ -534,6 +531,8 @@ Error RPCServer::ModifyItem(cproto::Context &ctx, p_string ns, int format, p_str case ModeDelete: err = db.WithTimeout(execTimeout).Delete(ns, item, qres); break; + default: + return Error(errParams, "Unexpected ItemModifyMode: %d", mode); } if (!err.ok()) return err; } else { @@ -550,6 +549,8 @@ Error RPCServer::ModifyItem(cproto::Context &ctx, p_string ns, int format, p_str case ModeDelete: err = db.WithTimeout(execTimeout).Delete(ns, item); break; + default: + return Error(errParams, "Unexpected ItemModifyMode: %d", mode); } if (!err.ok()) return err; qres.AddItem(item); @@ -577,51 +578,49 @@ Error RPCServer::ModifyItem(cproto::Context &ctx, p_string ns, int format, p_str return sendResults(ctx, qres, RPCQrId(), opts); } -Error RPCServer::DeleteQuery(cproto::Context &ctx, p_string queryBin, std::optional flagsOpts) { - Query query; - Serializer ser(queryBin.data(), queryBin.size()); +Error RPCServer::DeleteQuery(cproto::Context &ctx, p_string queryBin, std::optional flagsOpts) noexcept { try { - query.Deserialize(ser); - } catch (Error &err) { - return err; - } - query.type_ = QueryDelete; - - QueryResults qres; - auto err = getDB(ctx, kRoleDataWrite).Delete(query, qres); - if (!err.ok()) { - return err; - } - int flags = kResultsWithItemID; - if (flagsOpts) { - flags = *flagsOpts; + Serializer ser(queryBin.data(), queryBin.size()); + Query query = Query::Deserialize(ser); + query.type_ = QueryDelete; + + QueryResults qres; + auto err = getDB(ctx, kRoleDataWrite).Delete(query, qres); + if (!err.ok()) { + return err; + } + int flags = kResultsWithItemID; + if (flagsOpts) { + flags = *flagsOpts; + } + int32_t ptVersion = -1; + ResultFetchOpts opts{ + .flags = flags, .ptVersions = {&ptVersion, 1}, .fetchOffset = 0, .fetchLimit = INT_MAX, .withAggregations = true}; + return sendResults(ctx, qres, RPCQrId(), opts); } - int32_t ptVersion = -1; - ResultFetchOpts opts{.flags = flags, .ptVersions = {&ptVersion, 1}, .fetchOffset = 0, .fetchLimit = INT_MAX, .withAggregations = true}; - return sendResults(ctx, qres, RPCQrId(), opts); + CATCH_AND_RETURN; } -Error RPCServer::UpdateQuery(cproto::Context &ctx, p_string queryBin, std::optional flagsOpts) { - Query query; - Serializer ser(queryBin.data(), queryBin.size()); +Error RPCServer::UpdateQuery(cproto::Context &ctx, p_string queryBin, std::optional flagsOpts) noexcept { try { - query.Deserialize(ser); - } catch (Error &err) { - return err; - } - query.type_ = QueryUpdate; + Serializer ser(queryBin.data(), queryBin.size()); + Query query = Query::Deserialize(ser); + query.type_ = QueryUpdate; + + QueryResults qres; + auto err = getDB(ctx, kRoleDataWrite).Update(query, qres); + if (!err.ok()) { + return err; + } - QueryResults qres; - auto err = getDB(ctx, kRoleDataWrite).Update(query, qres); - if (!err.ok()) { - return err; + int32_t ptVersion = -1; + int flags = kResultsWithItemID | kResultsWithPayloadTypes | kResultsCJson; + if (flagsOpts) flags = *flagsOpts; + ResultFetchOpts opts{ + .flags = flags, .ptVersions = {&ptVersion, 1}, .fetchOffset = 0, .fetchLimit = INT_MAX, .withAggregations = true}; + return sendResults(ctx, qres, RPCQrId(), opts); } - - int32_t ptVersion = -1; - int flags = kResultsWithItemID | kResultsWithPayloadTypes | kResultsCJson; - if (flagsOpts) flags = *flagsOpts; - ResultFetchOpts opts{.flags = flags, .ptVersions = {&ptVersion, 1}, .fetchOffset = 0, .fetchLimit = INT_MAX, .withAggregations = true}; - return sendResults(ctx, qres, RPCQrId(), opts); + CATCH_AND_RETURN; } Reindexer RPCServer::getDB(cproto::Context &ctx, UserRole role) { @@ -659,8 +658,10 @@ Error RPCServer::sendResults(cproto::Context &ctx, QueryResults &qres, RPCQrId i freeQueryResults(ctx, id); id.main = -1; id.uid = RPCQrWatcher::kUninitialized; + // NOLINTBEGIN(bugprone-empty-catch) } catch (...) { } + // NOLINTEND(bugprone-empty-catch) } return err; } @@ -801,7 +802,7 @@ Error RPCServer::Select(cproto::Context &ctx, p_string queryBin, int flags, int Query query; Serializer ser(queryBin); try { - query.Deserialize(ser); + query = Query::Deserialize(ser); } catch (Error &err) { return err; } diff --git a/cpp_src/server/rpcserver.h b/cpp_src/server/rpcserver.h index bc75b3f3f..da981071f 100644 --- a/cpp_src/server/rpcserver.h +++ b/cpp_src/server/rpcserver.h @@ -86,14 +86,14 @@ class RPCServer { Error StartTransaction(cproto::Context &ctx, p_string nsName); Error AddTxItem(cproto::Context &ctx, int format, p_string itemData, int mode, p_string percepsPack, int stateToken, int64_t txID); - Error DeleteQueryTx(cproto::Context &ctx, p_string query, int64_t txID); - Error UpdateQueryTx(cproto::Context &ctx, p_string query, int64_t txID); + Error DeleteQueryTx(cproto::Context &ctx, p_string query, int64_t txID) noexcept; + Error UpdateQueryTx(cproto::Context &ctx, p_string query, int64_t txID) noexcept; Error CommitTx(cproto::Context &ctx, int64_t txId, std::optional flags); Error RollbackTx(cproto::Context &ctx, int64_t txId); - Error DeleteQuery(cproto::Context &ctx, p_string query, std::optional flags); - Error UpdateQuery(cproto::Context &ctx, p_string query, std::optional flags); + Error DeleteQuery(cproto::Context &ctx, p_string query, std::optional flags) noexcept; + Error UpdateQuery(cproto::Context &ctx, p_string query, std::optional flags) noexcept; Error Select(cproto::Context &ctx, p_string query, int flags, int limit, p_string ptVersions); Error SelectSQL(cproto::Context &ctx, p_string query, int flags, int limit, p_string ptVersions); @@ -112,7 +112,7 @@ class RPCServer { void OnResponse(cproto::Context &ctx); protected: - Error execSqlQueryByType(std::string_view sqlQuery, reindexer::QueryResults &res, cproto::Context &ctx); + Error execSqlQueryByType(std::string_view sqlQuery, reindexer::QueryResults &res, cproto::Context &ctx) noexcept; Error sendResults(cproto::Context &ctx, QueryResults &qr, RPCQrId id, const ResultFetchOpts &opts); Error processTxItem(DataFormat format, std::string_view itemData, Item &item, ItemModifyMode mode, int stateToken) const noexcept; diff --git a/cpp_src/tools/filecontentwatcher.h b/cpp_src/tools/filecontentwatcher.h index 13ea5a555..6297fc936 100644 --- a/cpp_src/tools/filecontentwatcher.h +++ b/cpp_src/tools/filecontentwatcher.h @@ -11,8 +11,7 @@ class FileContetWatcher { void SetFilepath(std::string filepath, bool enable = false) noexcept { assertrx(!hasFilepath_.load(std::memory_order_acquire)); filepath_ = std::move(filepath); - auto stat = fs::StatTime(filepath_); - lastReplConfMTime_.store(stat.mtime, std::memory_order_relaxed); + lastReplConfMTime_.store(fs::StatTime(filepath_).mtime, std::memory_order_relaxed); hasFilepath_.store(true, std::memory_order_release); if (enable) { isEnabled_.store(true, std::memory_order_release); @@ -31,18 +30,21 @@ class FileContetWatcher { if (!isEnabled_.load(std::memory_order_acquire) || !hasFilepath_.load(std::memory_order_acquire)) { return false; } - auto stat = fs::StatTime(filepath_); - if (stat.mtime > 0) { - auto lastReplConfMTime = lastReplConfMTime_.load(std::memory_order_acquire); - if (lastReplConfMTime != stat.mtime) { - if (lastReplConfMTime_.compare_exchange_strong(lastReplConfMTime, stat.mtime, std::memory_order_acq_rel)) { - auto res = fs::ReadFile(filepath_, content); - if (res < 0) { - content.clear(); - } - std::lock_guard lck(mtx_); - if (content != expectedContent_) { - return true; + auto mtime = fs::StatTime(filepath_).mtime; + if (mtime > 0) { + if (lastReplConfMTime_.load(std::memory_order_acquire) != mtime) { + std::lock_guard lck(mtx_); + mtime = fs::StatTime(filepath_).mtime; + if (mtime > 0) { + if (lastReplConfMTime_.load(std::memory_order_relaxed) != mtime) { + lastReplConfMTime_.store(mtime, std::memory_order_release); + auto res = fs::ReadFile(filepath_, content); + if (res < 0) { + content.clear(); + } + if (content != expectedContent_) { + return true; + } } } } @@ -53,18 +55,18 @@ class FileContetWatcher { template Error RewriteFile(std::string content, PredicatT hasSameContent) { if (!isEnabled_.load(std::memory_order_acquire) || !hasFilepath_.load(std::memory_order_acquire)) { - return errOK; + return Error(); } - std::string tmpPath = filepath_ + ".tmp"; std::string curContent; auto res = fs::ReadFile(filepath_, curContent); if (res < 0) { - return errOK; + return Error(); } if (hasSameContent(curContent)) { - return errOK; + return Error(); } + const std::string tmpPath = filepath_ + ".tmp"; std::lock_guard lck(mtx_); res = fs::WriteFile(tmpPath, content); if (res < 0 || static_cast(res) != content.size()) { @@ -75,7 +77,11 @@ class FileContetWatcher { return Error(errParams, "Unable to rename tmp file from [%s] to [%s]. Reason: %s", tmpPath, filepath_, strerror(errno)); } expectedContent_ = std::move(content); - return errOK; + auto stat = fs::StatTime(filepath_); + if (stat.mtime > 0) { + lastReplConfMTime_.store(stat.mtime, std::memory_order_release); + } + return Error(); } private: diff --git a/cpp_src/tools/fsops.cc b/cpp_src/tools/fsops.cc index e7d8db748..5fbfcae71 100644 --- a/cpp_src/tools/fsops.cc +++ b/cpp_src/tools/fsops.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include "errors.h" #include "tools/oscompat.h" @@ -177,7 +178,16 @@ std::string GetCwd() { return std::string(getcwd(buff, FILENAME_MAX)); } +static std::string tmpDir; +static std::mutex tmpDirMtx; + std::string GetTempDir() { + { + std::lock_guard lck(tmpDirMtx); + if (!tmpDir.empty()) { + return tmpDir; + } + } #ifdef _WIN32 char tmpBuf[512]; *tmpBuf = 0; @@ -190,6 +200,11 @@ std::string GetTempDir() { #endif } +void SetTempDir(std::string &&dir) noexcept { + std::lock_guard lck(tmpDirMtx); + tmpDir = std::move(dir); +} + std::string GetHomeDir() { const char *homeDir = getenv("HOME"); if (homeDir && *homeDir) return homeDir; @@ -355,5 +370,6 @@ std::string GetRelativePath(const std::string &path, unsigned maxUp) { rpath.append(path.begin() + same, path.end()); return rpath; } + } // namespace fs } // namespace reindexer diff --git a/cpp_src/tools/fsops.h b/cpp_src/tools/fsops.h index 46d56db4c..015ef0a66 100644 --- a/cpp_src/tools/fsops.h +++ b/cpp_src/tools/fsops.h @@ -37,6 +37,7 @@ TimeStats StatTime(const std::string &path); std::string GetCwd(); std::string GetDirPath(const std::string &path); std::string GetTempDir(); +void SetTempDir(std::string &&dir) noexcept; std::string GetHomeDir(); std::string GetRelativePath(const std::string &path, unsigned maxUp = 1024); inline int Rename(const std::string &from, const std::string &to) { return rename(from.c_str(), to.c_str()); } diff --git a/cpp_src/tools/jsonstring.h b/cpp_src/tools/jsonstring.h index 34c6eeb56..36601af0a 100644 --- a/cpp_src/tools/jsonstring.h +++ b/cpp_src/tools/jsonstring.h @@ -71,12 +71,15 @@ inline void encode(uint8_t *p, uint64_t l, std::vector> p[-3] = (uptr >> 8) & 0xFF; p[-4] = (uptr >> 16) & 0xFF; p[-5] = (uptr >> 24) & 0xFF; - if constexpr (sizeof(uintptr_t) == 8) { - p[-6] = (uptr >> 32) & 0xFF; - p[-7] = (uptr >> 40) & 0xFF; - p[-8] = (uptr >> 48) & 0xFF; - p[-9] = (uptr >> 56) & 0xFF; - } +#if UINTPTR_MAX == 0xFFFFFFFF +#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF + p[-6] = (uptr >> 32) & 0xFF; + p[-7] = (uptr >> 40) & 0xFF; + p[-8] = (uptr >> 48) & 0xFF; + p[-9] = (uptr >> 56) & 0xFF; +#else + static_assert(false, "Unexpected uintptr_t size"); +#endif } else { // Put length p[0] = l & 0xFF; diff --git a/cpp_src/tools/serializer.cc b/cpp_src/tools/serializer.cc index ae4880b77..2b7dd1a87 100644 --- a/cpp_src/tools/serializer.cc +++ b/cpp_src/tools/serializer.cc @@ -3,7 +3,6 @@ #include "core/keyvalue/p_string.h" #include "estl/span.h" #include "tools/errors.h" -#include "vendor/double-conversion/double-conversion.h" #include "vendor/itoa/itoa.h" namespace reindexer { @@ -81,19 +80,6 @@ void WrSerializer::VStringHelper::End() { } } -WrSerializer &WrSerializer::operator<<(double v) { - grow(32); - double_conversion::StringBuilder builder(reinterpret_cast(buf_ + len_), 32); - int flags = - double_conversion::DoubleToStringConverter::UNIQUE_ZERO | double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; - double_conversion::DoubleToStringConverter dc(flags, NULL, NULL, 'e', -6, 21, 0, 0); - - dc.ToShortest(v, &builder); - len_ += builder.position(); - - return *this; -} - void WrSerializer::PrintJsonString(std::string_view str, PrintJsonStringMode mode) { const char *s = str.data(); size_t l = str.size(); diff --git a/cpp_src/tools/serializer.h b/cpp_src/tools/serializer.h index 1765279db..f370263ce 100644 --- a/cpp_src/tools/serializer.h +++ b/cpp_src/tools/serializer.h @@ -7,6 +7,7 @@ #include "estl/chunk.h" #include "estl/one_of.h" #include "estl/span.h" +#include "tools/stringstools.h" #include "tools/varint.h" char *i32toa(int32_t value, char *buffer); @@ -228,7 +229,6 @@ class WrSerializer { }); } -public: // Put slice with 4 bytes len header void PutSlice(std::string_view slice) { PutUInt32(slice.size()); @@ -237,7 +237,9 @@ class WrSerializer { len_ += slice.size(); } - struct SliceHelper { +private: + class [[nodiscard]] SliceHelper { + public: SliceHelper(WrSerializer *ser, size_t pos) noexcept : ser_(ser), pos_(pos) {} SliceHelper(const SliceHelper &) = delete; SliceHelper operator=(const SliceHelper &) = delete; @@ -258,11 +260,14 @@ class WrSerializer { ser_ = nullptr; } + private: WrSerializer *ser_; size_t pos_; }; - struct VStringHelper { +public: + class [[nodiscard]] VStringHelper { + public: VStringHelper() noexcept : ser_(nullptr), pos_(0) {} VStringHelper(WrSerializer *ser, size_t pos) noexcept : ser_(ser), pos_(pos) {} VStringHelper(const VStringHelper &) = delete; @@ -277,9 +282,9 @@ class WrSerializer { return *this; } ~VStringHelper() { End(); } - void End(); + private: WrSerializer *ser_; size_t pos_; }; @@ -311,6 +316,10 @@ class WrSerializer { memcpy(&buf_[len_], &v, sizeof(v)); len_ += sizeof(v); } + void PutDoubleStrNoTrailing(double v) { + grow(32); + len_ += double_to_str_no_trailing(v, reinterpret_cast(buf_ + len_), 32); + } template ::value>::type * = nullptr> WrSerializer &operator<<(T k) { @@ -345,7 +354,11 @@ class WrSerializer { Write(v ? "true"sv : "false"sv); return *this; } - WrSerializer &operator<<(double v); + WrSerializer &operator<<(double v) { + grow(32); + len_ += double_to_str(v, reinterpret_cast(buf_ + len_), 32); + return *this; + } WrSerializer &operator<<(Uuid uuid) { grow(Uuid::kStrFormLen + 2); buf_[len_] = '\''; diff --git a/cpp_src/tools/stringstools.cc b/cpp_src/tools/stringstools.cc index 1517c379b..dbf99ecf1 100644 --- a/cpp_src/tools/stringstools.cc +++ b/cpp_src/tools/stringstools.cc @@ -3,19 +3,126 @@ #include #include #include -#include #include #include "atoi/atoi.h" +#include "estl/fast_hash_map.h" #include "itoa/itoa.h" #include "tools/assertrx.h" #include "tools/customlocal.h" #include "tools/randomgenerator.h" #include "tools/stringstools.h" #include "utf8cpp/utf8.h" +#include "vendor/double-conversion/double-conversion.h" namespace reindexer { +namespace stringtools_impl { + +static int double_to_str(double v, char *buf, int capacity, int flags) { + double_conversion::StringBuilder builder(buf, capacity); + double_conversion::DoubleToStringConverter dc(flags, NULL, NULL, 'e', -6, 21, 0, 0); + + if (!dc.ToShortest(v, &builder)) { + // NaN/Inf are not allowed here + throw Error(errParams, "Unable to convert '%f' to string", v); + } + return builder.position(); +} + +static std::pair word2Pos(std::string_view str, int wordPos, int endPos, const std::string &extraWordSymbols) { + auto wordStartIt = str.begin(); + auto wordEndIt = str.begin(); + auto it = str.begin(); + assertrx(endPos > wordPos); + int numWords = endPos - (wordPos + 1); + for (; it != str.end();) { + auto ch = utf8::unchecked::next(it); + + while (it != str.end() && extraWordSymbols.find(ch) == std::string::npos && !IsAlpha(ch) && !IsDigit(ch)) { + wordStartIt = it; + ch = utf8::unchecked::next(it); + } + + while (IsAlpha(ch) || IsDigit(ch) || extraWordSymbols.find(ch) != std::string::npos) { + wordEndIt = it; + if (it == str.end()) break; + ch = utf8::unchecked::next(it); + } + + if (wordStartIt != it) { + if (!wordPos) + break; + else { + wordPos--; + wordStartIt = it; + } + } + } + + for (; numWords != 0 && it != str.end(); numWords--) { + auto ch = utf8::unchecked::next(it); + + while (it != str.end() && !IsAlpha(ch) && !IsDigit(ch)) { + ch = utf8::unchecked::next(it); + } + + while (IsAlpha(ch) || IsDigit(ch) || extraWordSymbols.find(ch) != std::string::npos) { + wordEndIt = it; + if (it == str.end()) break; + ch = utf8::unchecked::next(it); + } + } + + return {int(std::distance(str.begin(), wordStartIt)), int(std::distance(str.begin(), wordEndIt))}; +} + +static std::string_view urldecode2(char *buf, std::string_view str) { + char a, b; + const char *src = str.data(); + char *dst = buf; + + for (size_t l = 0; l < str.length(); l++) { + if (l + 2 < str.length() && (*src == '%') && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) { + if (a >= 'a') a -= 'a' - 'A'; + if (a >= 'A') + a -= ('A' - 10); + else + a -= '0'; + if (b >= 'a') b -= 'a' - 'A'; + if (b >= 'A') + b -= ('A' - 10); + else + b -= '0'; + *dst++ = 16 * a + b; + src += 3; + l += 2; + } else if (*src == '+') { + *dst++ = ' '; + src++; + } else { + *dst++ = *src++; + } + } + *dst = '\0'; + return std::string_view(buf, dst - buf); +} + +// Sat Jul 15 14 : 18 : 56 2017 GMT + +static const char *kDaysOfWeek[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; +static const char *kMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +inline static char *strappend(char *dst, const char *src) noexcept { + while (*src) *dst++ = *src++; + return dst; +} + +static fast_hash_map kStrictModes = { + {"", StrictModeNotSet}, {"none", StrictModeNone}, {"names", StrictModeNames}, {"indexes", StrictModeIndexes}}; + +} // namespace stringtools_impl + std::string toLower(std::string_view src) { std::string ret; ret.reserve(src.size()); @@ -238,63 +345,13 @@ Pos wordToByteAndCharPos(std::string_view str, int wordPosition, const std::stri template WordPositionEx wordToByteAndCharPos(std::string_view str, int wordPosition, const std::string &extraWordSymbols); template WordPosition wordToByteAndCharPos(std::string_view str, int wordPosition, const std::string &extraWordSymbols); -static std::pair word2Pos(std::string_view str, int wordPos, int endPos, const std::string &extraWordSymbols) { - auto wordStartIt = str.begin(); - auto wordEndIt = str.begin(); - auto it = str.begin(); - assertrx(endPos > wordPos); - int numWords = endPos - (wordPos + 1); - for (; it != str.end();) { - auto ch = utf8::unchecked::next(it); - - while (it != str.end() && extraWordSymbols.find(ch) == std::string::npos && !IsAlpha(ch) && !IsDigit(ch)) { - wordStartIt = it; - ch = utf8::unchecked::next(it); - } - - while (IsAlpha(ch) || IsDigit(ch) || extraWordSymbols.find(ch) != std::string::npos) { - wordEndIt = it; - if (it == str.end()) break; - ch = utf8::unchecked::next(it); - } - - if (wordStartIt != it) { - if (!wordPos) - break; - else { - wordPos--; - wordStartIt = it; - } - } - } - - for (; numWords != 0 && it != str.end(); numWords--) { - auto ch = utf8::unchecked::next(it); - - while (it != str.end() && !IsAlpha(ch) && !IsDigit(ch)) { - ch = utf8::unchecked::next(it); - } - - while (IsAlpha(ch) || IsDigit(ch) || extraWordSymbols.find(ch) != std::string::npos) { - wordEndIt = it; - if (it == str.end()) break; - ch = utf8::unchecked::next(it); - } - } - - return {int(std::distance(str.begin(), wordStartIt)), int(std::distance(str.begin(), wordEndIt))}; -} - -Word2PosHelper::Word2PosHelper(std::string_view data, const std::string &extraWordSymbols) - : data_(data), lastWordPos_(0), lastOffset_(0), extraWordSymbols_(extraWordSymbols) {} - std::pair Word2PosHelper::convert(int wordPos, int endPos) { if (wordPos < lastWordPos_) { lastWordPos_ = 0; lastOffset_ = 0; } - auto ret = word2Pos(data_.substr(lastOffset_), wordPos - lastWordPos_, endPos - lastWordPos_, extraWordSymbols_); + auto ret = stringtools_impl::word2Pos(data_.substr(lastOffset_), wordPos - lastWordPos_, endPos - lastWordPos_, extraWordSymbols_); ret.first += lastOffset_; ret.second += lastOffset_; lastOffset_ = ret.first; @@ -453,62 +510,23 @@ int collateCompare(std::string_view lhs, std::string_view rhs, cons return res ? res : ((l1 < l2) ? -1 : (l1 > l2) ? 1 : 0); } -static std::string_view urldecode2(char *buf, std::string_view str) { - char a, b; - const char *src = str.data(); - char *dst = buf; - - for (size_t l = 0; l < str.length(); l++) { - if (l + 2 < str.length() && (*src == '%') && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) { - if (a >= 'a') a -= 'a' - 'A'; - if (a >= 'A') - a -= ('A' - 10); - else - a -= '0'; - if (b >= 'a') b -= 'a' - 'A'; - if (b >= 'A') - b -= ('A' - 10); - else - b -= '0'; - *dst++ = 16 * a + b; - src += 3; - l += 2; - } else if (*src == '+') { - *dst++ = ' '; - src++; - } else { - *dst++ = *src++; - } - } - *dst = '\0'; - return std::string_view(buf, dst - buf); -} - std::string urldecode2(std::string_view str) { std::string ret(str.length(), ' '); - std::string_view sret = urldecode2(&ret[0], str); + std::string_view sret = stringtools_impl::urldecode2(&ret[0], str); ret.resize(sret.size()); return ret; } -// Sat Jul 15 14 : 18 : 56 2017 GMT - -static const char *daysOfWeek[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; -static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - -inline static char *strappend(char *dst, const char *src) noexcept { - while (*src) *dst++ = *src++; - return dst; -} - int fast_strftime(char *buf, const tm *tm) { char *d = buf; - if (unsigned(tm->tm_wday) < sizeof(daysOfWeek) / sizeof daysOfWeek[0]) d = strappend(d, daysOfWeek[tm->tm_wday]); - d = strappend(d, ", "); + if (unsigned(tm->tm_wday) < sizeof(stringtools_impl::kDaysOfWeek) / sizeof stringtools_impl::kDaysOfWeek[0]) + d = stringtools_impl::strappend(d, stringtools_impl::kDaysOfWeek[tm->tm_wday]); + d = stringtools_impl::strappend(d, ", "); d = i32toa(tm->tm_mday, d); *d++ = ' '; - if (unsigned(tm->tm_mon) < sizeof(months) / sizeof months[0]) d = strappend(d, months[tm->tm_mon]); + if (unsigned(tm->tm_mon) < sizeof(stringtools_impl::kMonths) / sizeof stringtools_impl::kMonths[0]) + d = stringtools_impl::strappend(d, stringtools_impl::kMonths[tm->tm_mon]); *d++ = ' '; d = i32toa(tm->tm_year + 1900, d); *d++ = ' '; @@ -517,7 +535,7 @@ int fast_strftime(char *buf, const tm *tm) { d = i32toa(tm->tm_min, d); *d++ = ':'; d = i32toa(tm->tm_sec, d); - d = strappend(d, " GMT"); + d = stringtools_impl::strappend(d, " GMT"); *d = 0; return d - buf; } @@ -546,8 +564,8 @@ bool validateUserNsName(std::string_view name) noexcept { return true; } -LogLevel logLevelFromString(const std::string &strLogLevel) { - static std::unordered_map levels = { +LogLevel logLevelFromString(std::string_view strLogLevel) { + static fast_hash_map levels = { {"none", LogNone}, {"warning", LogWarning}, {"error", LogError}, {"info", LogInfo}, {"trace", LogTrace}}; auto configLevelIt = levels.find(strLogLevel); @@ -557,25 +575,21 @@ LogLevel logLevelFromString(const std::string &strLogLevel) { return LogNone; } -static std::unordered_map strictModes = { - {"", StrictModeNotSet}, {"none", StrictModeNone}, {"names", StrictModeNames}, {"indexes", StrictModeIndexes}}; - -StrictMode strictModeFromString(const std::string &strStrictMode) { - auto configModeIt = strictModes.find(strStrictMode); - if (configModeIt != strictModes.end()) { +StrictMode strictModeFromString(std::string_view strStrictMode) { + auto configModeIt = stringtools_impl::kStrictModes.find(strStrictMode); + if (configModeIt != stringtools_impl::kStrictModes.end()) { return configModeIt->second; } return StrictModeNotSet; } std::string_view strictModeToString(StrictMode mode) { - for (auto &it : strictModes) { + for (auto &it : stringtools_impl::kStrictModes) { if (it.second == mode) { return it.first; } } - static std::string_view empty{""}; - return empty; + return std::string_view(); } bool isPrintable(std::string_view str) noexcept { @@ -635,6 +649,26 @@ int64_t stoll(std::string_view sl) { return ret; } +int double_to_str(double v, char *buf, int capacity) { + const int flags = double_conversion::DoubleToStringConverter::UNIQUE_ZERO | + double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN | + double_conversion::DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT | + double_conversion::DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT; + return stringtools_impl::double_to_str(v, buf, capacity, flags); +} +int double_to_str_no_trailing(double v, char *buf, int capacity) { + const int flags = + double_conversion::DoubleToStringConverter::UNIQUE_ZERO | double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; + return stringtools_impl::double_to_str(v, buf, capacity, flags); +} +std::string double_to_str(double v) { + std::string res; + res.resize(32); + auto len = double_to_str(v, res.data(), res.size()); + res.resize(len); + return res; +} + std::string randStringAlph(size_t len) { constexpr std::string_view symbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; std::string result; diff --git a/cpp_src/tools/stringstools.h b/cpp_src/tools/stringstools.h index ed0e1a41b..97c451577 100644 --- a/cpp_src/tools/stringstools.h +++ b/cpp_src/tools/stringstools.h @@ -63,7 +63,8 @@ int getUTF8StringCharactersCount(std::string_view str) noexcept; class Word2PosHelper { public: - Word2PosHelper(std::string_view data, const std::string& extraWordSymbols); + Word2PosHelper(std::string_view data, const std::string& extraWordSymbols) noexcept + : data_(data), lastWordPos_(0), lastOffset_(0), extraWordSymbols_(extraWordSymbols) {} std::pair convert(int wordPos, int endPos); protected: @@ -145,12 +146,15 @@ std::string urldecode2(std::string_view str); int stoi(std::string_view sl); std::optional try_stoi(std::string_view sl); int64_t stoll(std::string_view sl); +int double_to_str(double v, char* buf, int capacity); +int double_to_str_no_trailing(double v, char* buf, int capacity); +std::string double_to_str(double v); bool validateObjectName(std::string_view name, bool allowSpecialChars) noexcept; bool validateUserNsName(std::string_view name) noexcept; RX_ALWAYS_INLINE bool isSystemNamespaceNameFast(std::string_view name) noexcept { return !name.empty() && name[0] == '#'; } -LogLevel logLevelFromString(const std::string& strLogLevel); -StrictMode strictModeFromString(const std::string& strStrictMode); +LogLevel logLevelFromString(std::string_view strLogLevel); +StrictMode strictModeFromString(std::string_view strStrictMode); std::string_view strictModeToString(StrictMode mode); inline bool iequals(std::string_view lhs, std::string_view rhs) noexcept { diff --git a/cpp_src/vendor/gason/gason.h b/cpp_src/vendor/gason/gason.h index 6e227f7a8..76c218d37 100644 --- a/cpp_src/vendor/gason/gason.h +++ b/cpp_src/vendor/gason/gason.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "estl/span.h" #include "tools/jsonstring.h" diff --git a/cpp_src/vendor/yaml-cpp/binary.cpp b/cpp_src/vendor/yaml-cpp/binary.cpp index 55fc1abd2..4e75b6628 100644 --- a/cpp_src/vendor/yaml-cpp/binary.cpp +++ b/cpp_src/vendor/yaml-cpp/binary.cpp @@ -37,6 +37,8 @@ std::string EncodeBase64(const unsigned char *data, std::size_t size) { *out++ = encoding[((data[1] & 0xf) << 2)]; *out++ = PAD; break; + default: + std::abort(); } ret.resize(out - &ret[0]); diff --git a/cpp_src/vendor/yaml-cpp/emitterutils.cpp b/cpp_src/vendor/yaml-cpp/emitterutils.cpp index f92106c43..4f9543d58 100644 --- a/cpp_src/vendor/yaml-cpp/emitterutils.cpp +++ b/cpp_src/vendor/yaml-cpp/emitterutils.cpp @@ -32,6 +32,7 @@ bool IsAnchorChar(int ch) { // test for ns-anchor-char return false; case 0x85: return true; + default:; } if (ch < 0x20) { diff --git a/cpp_src/vendor/yaml-cpp/exp.cpp b/cpp_src/vendor/yaml-cpp/exp.cpp index 976ef13f9..814e68894 100644 --- a/cpp_src/vendor/yaml-cpp/exp.cpp +++ b/cpp_src/vendor/yaml-cpp/exp.cpp @@ -121,6 +121,7 @@ std::string Escape(Stream& in) { return Escape(in, 4); case 'U': return Escape(in, 8); + default:; } std::stringstream msg; diff --git a/cpp_src/vendor/yaml-cpp/stream.cpp b/cpp_src/vendor/yaml-cpp/stream.cpp index ed58ef8cb..c387beb81 100644 --- a/cpp_src/vendor/yaml-cpp/stream.cpp +++ b/cpp_src/vendor/yaml-cpp/stream.cpp @@ -107,6 +107,7 @@ inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) { return uictFE; case 0xFF: return uictFF; + default:; } if ((ch > 0) && (ch < 0xFF)) { diff --git a/describer.go b/describer.go index ed494bed8..b356b3cba 100644 --- a/describer.go +++ b/describer.go @@ -85,7 +85,7 @@ type CacheMemStat struct { type LsnT struct { // Operation counter Counter int64 `json:"counter"` - // Node identifyer + // Node identifier ServerId int `json:"server_id"` } diff --git a/dsl/dsl.go b/dsl/dsl.go index 0b9509219..e110dde15 100644 --- a/dsl/dsl.go +++ b/dsl/dsl.go @@ -1,12 +1,15 @@ package dsl import ( + "bytes" "encoding/json" "errors" "fmt" "reflect" + "regexp" "strconv" "strings" + "sync/atomic" ) /* @@ -25,28 +28,46 @@ rxDB := reindexer.NewReindex(...) jsonDSL := "{...}" // Contains JSON string, corresponding the DSL's format var dslQ dsl.DSL err := json.Unmarshal([]byte(jsonDSL), &dslQ) +// OR: dslQ, err := dsl.DecodeJSON([]byte(jsonDSL)) +// DecodeJSON allows to use dsl's strict mode for the main json object (json.Unmarshal performs strict checks for the internal objects only) q, err := rxDB.QueryFrom(dslQ) + +Use dsl.EnabeStrictMode and dsl.DisableStrictMode to control dsl parsing strict mode. If strict mode is enabled, any unknow field in the JSON DSL will cause unmarshling error. +Strict mode is disabled by default. */ +const ( + AggSum = "sum" + AggAvg = "avg" + AggMin = "min" + AggMax = "max" + AggCount = "count" + AggCountCached = "count_cached" + AggFacet = "facet" + AggDistinct = "distinct" +) + +var dslStrictMode = int32(0) + type DSL struct { Namespace string `json:"namespace"` - Offset int `json:"offset"` - Limit int `json:"limit"` - Distinct string `json:"distinct"` // deprecated, use aggregation with type AggDistinct instead - Sort Sort `json:"sort"` - Filters []Filter `json:"filters"` + Offset int `json:"offset,omitempty"` + Limit int `json:"limit,omitempty"` + Distinct string `json:"distinct,omitempty"` // deprecated, use aggregation with type AggDistinct instead + Sort Sort `json:"sort,omitempty"` + Filters []Filter `json:"filters,omitempty"` Explain bool `json:"explain,omitempty"` ReqTotal bool `json:"req_total,omitempty"` WithRank bool `json:"select_with_rank,omitempty"` - Aggregations []Aggregation `json:"aggregations"` + Aggregations []Aggregation `json:"aggregations,omitempty"` } type Aggregation struct { - AggType int `json:"type"` - Sort []Sort `json:"sort"` - Limit int `json:"limit"` - Offset int `json:"offset"` + AggType string `json:"type"` + Sort []Sort `json:"sort,omitempty"` + Limit int `json:"limit,omitempty"` + Offset int `json:"offset,omitempty"` Fields []string `json:"fields"` } @@ -59,45 +80,66 @@ type Sort struct { } type Filter struct { - Op string - Field string - Joined *JoinQuery `json:"Joined,omitempty"` - Cond string - Value interface{} - Filters []Filter `json:"Filters,omitempty"` + Op string `json:"op,omitempty"` + Field string `json:"field,omitempty"` + Joined *JoinQuery `json:"join_query,omitempty"` + SubQ *SubQuery `json:"subquery,omitempty"` + Cond string `json:"cond,omitempty"` + Value interface{} `json:"value,omitempty"` + Filters []Filter `json:"filters,omitempty"` } type JoinOnCondition struct { LeftField string `json:"left_field"` RightField string `json:"right_field"` - Op string `json:"op"` + Op string `json:"op,omitempty"` Cond string `json:"cond"` } -type JoinQuery struct { - Namespace string - Type string - Sort Sort - Filters []Filter - Offset int - Limit int - On []JoinOnCondition -} - -type joinQuery struct { +type joinQueryBase struct { Namespace string `json:"namespace"` Type string `json:"type,omitempty"` Sort Sort `json:"sort,omitempty"` - Filters []filter `json:"filters,omitempty"` Offset int `json:"offset,omitempty"` Limit int `json:"limit,omitempty"` On []JoinOnCondition `json:"on"` } +type JoinQuery struct { + joinQueryBase + Filters []Filter `json:"filters,omitempty"` +} + +type joinQuery struct { + joinQueryBase + Filters []filter `json:"filters,omitempty"` +} + +type SubQueryBase struct { + Namespace string `json:"namespace"` + Offset int `json:"offset,omitempty"` + Limit int `json:"limit,omitempty"` + Sort Sort `json:"sort,omitempty"` + ReqTotal bool `json:"req_total,omitempty"` + Aggregations []Aggregation `json:"aggregations,omitempty"` + SelectFilter []string `json:"select_filter,omitempty"` +} + +type subQuery struct { + SubQueryBase + Filters []filter `json:"filters,omitempty"` +} + +type SubQuery struct { + SubQueryBase + Filters []Filter `json:"filters,omitempty"` +} + type filter struct { - Op string `json:"op"` + Op string `json:"op,omitempty"` Field string `json:"field,omitempty"` Joined *joinQuery `json:"join_query,omitempty"` + SubQ *subQuery `json:"subquery,omitempty"` Cond string `json:"cond,omitempty"` Value value `json:"value,omitempty"` Filters []filter `json:"filters,omitempty"` @@ -107,9 +149,38 @@ type value struct { data string } +func EnabeStrictMode() { + atomic.StoreInt32(&dslStrictMode, 1) +} +func DisableStrictMode() { + atomic.StoreInt32(&dslStrictMode, 0) +} +func DecodeJSON(data []byte) (*DSL, error) { + var dslQ DSL + var err error + if atomic.LoadInt32(&dslStrictMode) == 1 { + dec := json.NewDecoder(bytes.NewReader(data)) + dec.DisallowUnknownFields() + err = dec.Decode(&dslQ) + } else { + err = json.Unmarshal(data, &dslQ) + } + if err != nil { + return nil, err + } + return &dslQ, nil +} + func (s *Sort) UnmarshalJSON(data []byte) error { sort := sort{} - err := json.Unmarshal(data, &sort) + var err error + if atomic.LoadInt32(&dslStrictMode) == 1 { + dec := json.NewDecoder(bytes.NewReader(data)) + dec.DisallowUnknownFields() + err = dec.Decode(&sort) + } else { + err = json.Unmarshal(data, &sort) + } if err != nil { return err } @@ -146,10 +217,10 @@ func (f *Filter) fillFilter(flt *filter) error { f.Cond = flt.Cond f.Field = flt.Field if flt.Joined != nil { - f.Joined = &JoinQuery{Namespace: flt.Joined.Namespace, + f.Joined = &JoinQuery{joinQueryBase: joinQueryBase{Namespace: flt.Joined.Namespace, Type: flt.Joined.Type, Sort: flt.Joined.Sort, Limit: flt.Joined.Limit, Offset: flt.Joined.Offset, - On: flt.Joined.On} + On: flt.Joined.On}} f.Joined.Filters = make([]Filter, len(flt.Joined.Filters)) for i := range f.Joined.Filters { err := f.Joined.Filters[i].fillFilter(&flt.Joined.Filters[i]) @@ -158,24 +229,54 @@ func (f *Filter) fillFilter(flt *filter) error { } } } + if flt.SubQ != nil { + f.SubQ = &SubQuery{SubQueryBase: SubQueryBase{Namespace: flt.SubQ.Namespace, + Limit: flt.SubQ.Limit, Offset: flt.SubQ.Offset, + ReqTotal: flt.SubQ.ReqTotal}} + f.SubQ.Filters = make([]Filter, len(flt.SubQ.Filters)) + for i := range f.SubQ.Filters { + err := f.SubQ.Filters[i].fillFilter(&flt.SubQ.Filters[i]) + if err != nil { + return err + } + } + f.SubQ.Aggregations = make([]Aggregation, len(flt.SubQ.Aggregations)) + copy(f.SubQ.Aggregations, flt.SubQ.Aggregations) + f.SubQ.SelectFilter = make([]string, len(flt.SubQ.SelectFilter)) + copy(f.SubQ.SelectFilter, flt.SubQ.SelectFilter) + } if len(flt.Filters) != 0 { f.Filters = make([]Filter, len(flt.Filters)) for i := range f.Filters { - f.Filters[i].fillFilter(&flt.Filters[i]) + err := f.Filters[i].fillFilter(&flt.Filters[i]) + if err != nil { + return err + } } } - if f.Field != "" { + if f.Field != "" || f.SubQ != nil { err := f.parseValue(flt.Value.data) if err != nil { return err } + } else if !checkValueIsEmpty(flt.Value.data) { + return errors.New("unable to use Value without Field/Subquery") + } else if flt.Cond != "" { + return errors.New("unable to use Cond without Field/Subquery/Value") } return nil } func (f *Filter) UnmarshalJSON(data []byte) error { flt := filter{} - err := json.Unmarshal(data, &flt) + var err error + if atomic.LoadInt32(&dslStrictMode) == 1 { + dec := json.NewDecoder(bytes.NewReader(data)) + dec.DisallowUnknownFields() + err = dec.Decode(&flt) + } else { + err = json.Unmarshal(data, &flt) + } if err != nil { return err } @@ -219,6 +320,15 @@ func (f *Filter) parseValuesArray(rawValues []interface{}) (interface{}, error) } } +var emptyArrayRegex = regexp.MustCompile(`\[\s*\]`) + +func checkValueIsEmpty(data string) bool { + if len(data) != 0 && data != `""` && data != "null" && data != "[]" && !emptyArrayRegex.MatchString(data) { + return false + } + return true +} + func (f *Filter) parseValue(data string) error { if strings.HasPrefix(data, `"$`) { f.Value = strings.Trim(data, `"`) @@ -282,7 +392,7 @@ func (f *Filter) parseValue(data string) error { f.Value = v } case "set", "range", "allset": - if len(data) == 0 || data == `[]` || data == "null" { + if len(data) == 0 || data == "[]" || data == "null" || emptyArrayRegex.MatchString(data) { f.Value = nil break } @@ -305,7 +415,7 @@ func (f *Filter) parseValue(data string) error { f.Value, err = f.parseValuesArray(rawValues) return err case "any", "empty": - if len(data) != 0 && data != `""` && data != "null" { + if !checkValueIsEmpty(data) { return fmt.Errorf("filter expects no arguments or null for '%s' condition", f.Cond) } f.Value = nil diff --git a/fulltext.md b/fulltext.md index e741225a2..672ab7e52 100644 --- a/fulltext.md +++ b/fulltext.md @@ -378,10 +378,10 @@ FtTyposDetailedConfig: config for more precise typos algorithm tuning. | | Parameter name | Type | Description | Default value | |---|:----------------------------:|:--------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------:| -| | MaxTypoDistance | int | Maximum distance between symbols in initial and target words to perform substitution. Check [typos handling](#typos-handling-details) section for detailed description. | 0 | -| | MaxSymbolPermutationDistance | int | aximum distance between same symbols in initial and target words to perform substitution (to handle cases, when two symbolws were switched with each other). Check [typos handling](#typos-handling-details) section for detailed description. | 1 | -| | MaxMissingLetters | int | Maximum number of symbols, which may be removed from the initial term to transform it into the result word. Check [typos handling](#typos-handling-details) section for detailed description. | 2 | -| | MaxExtraLetters | int | Maximum number of symbols, which may be added to the initial term to transform it into the result word. Check [typos handling](#typos-handling-details) section for detailed description. | 2 | +| | MaxTypoDistance | int | Maximum distance between symbols in initial and target words to perform substitution. Check [typos handling](#typos-handling-details) section for detailed description. | 0 | +| | MaxSymbolPermutationDistance | int | aximum distance between same symbols in initial and target words to perform substitution (to handle cases, when two symbolws were switched with each other). Check [typos handling](#typos-handling-details) section for detailed description. | 1 | +| | MaxMissingLetters | int | Maximum number of symbols, which may be removed from the initial term to transform it into the result word. Check [typos handling](#typos-handling-details) section for detailed description. | 2 | +| | MaxExtraLetters | int | Maximum number of symbols, which may be added to the initial term to transform it into the result word. Check [typos handling](#typos-handling-details) section for detailed description. | 2 | ### Base ranking config diff --git a/iterator.go b/iterator.go index 3dc52ad66..d70832764 100644 --- a/iterator.go +++ b/iterator.go @@ -292,7 +292,10 @@ func (it *Iterator) readItem(toObj interface{}) (item interface{}, rank int) { } it.current.joinObj[nsIndex] = subitems - it.join(nsIndex, nsIndexOffset, params.nsid, item) + it.err = it.join(nsIndex, nsIndexOffset, params.nsid, item) + if it.err != nil { + return + } } return } @@ -346,7 +349,7 @@ func (it *Iterator) fetchResults() { } } -func (it *Iterator) join(nsIndex, nsIndexOffset, parentNsID int, item interface{}) { +func (it *Iterator) join(nsIndex, nsIndexOffset, parentNsID int, item interface{}) error { var field string var handler JoinHandler if parentNsID == 0 { @@ -360,19 +363,24 @@ func (it *Iterator) join(nsIndex, nsIndexOffset, parentNsID int, item interface{ subitems := it.current.joinObj[nsIndex] if handler != nil { if !handler(field, item, subitems) { - return + return nil } } if joinable, ok := item.(Joinable); ok { joinable.Join(field, subitems, it.queryContext) + } else if it.query.db.strictJoinHandlers { + if handler == nil { + return bindings.NewError(fmt.Sprintf("join handler is missing. Field tag: '%s', struct: '%s', joined namespace: '%s'", + field, it.nsArray[0].rtype, it.nsArray[nsIndex+nsIndexOffset].name), ErrCodeStrictMode) + } else { + return bindings.NewError(fmt.Sprintf("join handler was found, but returned 'true' and the field was handled via reflection. Field tag: '%s', struct: '%s', joined namespace: '%s'", + field, it.nsArray[0].rtype, it.nsArray[nsIndex+nsIndexOffset].name), ErrCodeStrictMode) + } } else { - v := getJoinedField(reflect.ValueOf(item), it.nsArray[parentNsID].joined, field) if !v.IsValid() { - panic(fmt.Errorf("Can't find field with tag '%s' in struct '%s' for put join results from '%s'", - field, - it.nsArray[0].rtype, - it.nsArray[nsIndex+nsIndexOffset].name)) + return bindings.NewError(fmt.Sprintf("can not find field with tag '%s' in struct '%s' for put join results from '%s'", + field, it.nsArray[0].rtype, it.nsArray[nsIndex+nsIndexOffset].name), ErrCodeLogic) } if v.IsNil() { v.Set(reflect.MakeSlice(reflect.SliceOf(reflect.PtrTo(it.nsArray[nsIndex+nsIndexOffset].rtype)), 0, len(subitems))) @@ -381,6 +389,7 @@ func (it *Iterator) join(nsIndex, nsIndexOffset, parentNsID int, item interface{ v.Set(reflect.Append(v, reflect.ValueOf(subitem))) } } + return nil } // Object returns current object. diff --git a/query.go b/query.go index 804fdbafe..c2f1be9cb 100644 --- a/query.go +++ b/query.go @@ -56,6 +56,9 @@ const ( queryUpdateFieldV2 = bindings.QueryUpdateFieldV2 queryBetweenFieldsCondition = bindings.QueryBetweenFieldsCondition queryAlwaysFalseCondition = bindings.QueryAlwaysFalseCondition + queryAlwaysTrueCondition = bindings.QueryAlwaysTrueCondition + querySubQueryCondition = bindings.QuerySubQueryCondition + queryFieldSubQueryCondition = bindings.QueryFieldSubQueryCondition ) // Constants for calc total @@ -262,9 +265,47 @@ func (q *Query) Where(index string, condition int, keys interface{}) *Query { t := reflect.TypeOf(keys) v := reflect.ValueOf(keys) - q.ser.PutVarCUInt(queryCondition) - q.ser.PutVString(index) + if keys != nil && (t == reflect.TypeOf((*Query)(nil)).Elem() || (t.Kind() == reflect.Ptr && t.Elem() == reflect.TypeOf((*Query)(nil)).Elem())) { + q.ser.PutVarCUInt(queryFieldSubQueryCondition) + q.ser.PutVarCUInt(q.nextOp) + q.ser.PutVString(index) + q.ser.PutVarCUInt(condition) + if t.Kind() == reflect.Ptr { + q.ser.PutVBytes(v.Interface().(*Query).ser.Bytes()) + } else { + subQuery := v.Interface().(Query) + q.ser.PutVBytes(subQuery.ser.Bytes()) + } + } else { + q.ser.PutVarCUInt(queryCondition) + q.ser.PutVString(index) + q.ser.PutVarCUInt(q.nextOp) + q.ser.PutVarCUInt(condition) + + if keys == nil { + q.ser.PutVarUInt(0) + } else if t.Kind() == reflect.Slice || t.Kind() == reflect.Array { + q.ser.PutVarCUInt(v.Len()) + for i := 0; i < v.Len(); i++ { + q.putValue(v.Index(i)) + } + } else { + q.ser.PutVarCUInt(1) + q.putValue(v) + } + } + q.queriesCount++ + q.nextOp = opAND + return q +} + +func (q *Query) WhereQuery(subQuery *Query, condition int, keys interface{}) *Query { + t := reflect.TypeOf(keys) + v := reflect.ValueOf(keys) + + q.ser.PutVarCUInt(querySubQueryCondition) q.ser.PutVarCUInt(q.nextOp) + q.ser.PutVBytes(subQuery.ser.Bytes()) q.ser.PutVarCUInt(condition) q.nextOp = opAND q.queriesCount++ @@ -731,9 +772,6 @@ func (q *Query) ExecCtx(ctx context.Context) *Iterator { if q.executed { q.panicTrace("Exec call on already executed query. You should create new Query") } - // if q.tx != nil { - // panic(errors.New("For tx query only Update or Delete operations are supported")) - // } q.executed = true @@ -756,9 +794,6 @@ func (q *Query) ExecToJsonCtx(ctx context.Context, jsonRoots ...string) *JSONIte if q.executed { q.panicTrace("Exec call on already executed query. You should create new Query") } - // if q.tx != nil { - // panic(errors.New("For tx query only Update or Delete operations are supported")) - // } q.executed = true @@ -1090,7 +1125,17 @@ func (q *Query) LeftJoin(q2 *Query, field string) *Query { } // JoinHandler registers join handler that will be called when join, registered on `field` value, finds a match +// Handler will be always set to the main query func (q *Query) JoinHandler(field string, handler JoinHandler) *Query { + if q.root != nil { + // Joined queries can not have JoinHandlers themselfs. Routing this call to the root query if current query is joined + for _, jq := range q.root.joinQueries { + if q == jq { + q.root.JoinHandler(field, handler) + return q + } + } + } index := -1 for i := range q.joinToFields { if strings.EqualFold(q.joinToFields[i], field) { diff --git a/readme.md b/readme.md index d1f023fec..65dbf595d 100644 --- a/readme.md +++ b/readme.md @@ -44,14 +44,15 @@ Storages are compatible between those versions, hovewer, replication configs are - [Nested Structs](#nested-structs) - [Sort](#sort) - [Text pattern search with LIKE condition](#text-pattern-search-with-like-condition) + - [Update queries](#update-queries) + - [Transactions and batch update](#transactions-and-batch-update) + - [Synchronous mode](#synchronous-mode) + - [Async batch mode](#async-batch-mode) + - [Transactions commit strategies](#transactions-commit-strategies) + - [Implementation notes](#implementation-notes) - [Join](#join) - [Joinable interface](#joinable-interface) - - [Update queries](#update-queries) - - [Transactions and batch update](#transactions-and-batch-update) - - [Synchronous mode](#synchronous-mode) - - [Async batch mode](#async-batch-mode) - - [Transactions commit strategies](#transactions-commit-strategies) - - [Implementation notes](#implementation-notes) + - [Subqueries (nested queries)](#subqueries-nested-queries) - [Complex Primary Keys and Composite Indexes](#complex-primary-keys-and-composite-indexes) - [Aggregations](#aggregations) - [Search in array fields with matching array indexes](#search-in-array-fields-with-matching-array-indexes) @@ -71,14 +72,18 @@ Storages are compatible between those versions, hovewer, replication configs are - [Debug queries](#debug-queries) - [Custom allocators support](#custom-allocators-support) - [Profiling](#profiling) + - [Heap profiling](#heap-profiling) + - [CPU profiling](#cpu-profiling) + - [Known profiling issues](#known-profiling-issues) - [Tracing](#tracing) - [Integration with other program languages](#integration-with-other-program-languages) - - [Reindexer-for-python](#reindexer-for-python) - - [Reindexer-for-java](#reindexer-for-java) + - [Reindexer for python](#pyreindexer-for-python) + - [Reindexer for java](#reindexer-for-java) + - [Spring wrapper](#spring-wrapper) - [3rd party open source connectors](#3rd-party-open-source-connectors) - [PHP](#php) - [Rust](#rust) - - [.NET](#.net) + - [.NET](#net) - [Limitations and known issues](#limitations-and-known-issues) - [Getting help](#getting-help) - [References](#references) @@ -545,7 +550,7 @@ type SortModeCustomItem struct { The very first character in this list has the highest priority, priority of the last character is the smallest one. It means that sorting algorithm will put items that start with the first character before others. If some characters are skipped their priorities would have their usual values (according to characters in the list). -## Text pattern search with LIKE condition +### Text pattern search with LIKE condition For simple searching text pattern in string fields condition `LIKE` can be used. It search strings which match a pattern. In the pattern `_` means any char and `%` means any sequence of chars. @@ -875,6 +880,55 @@ func (item *ItemWithJoin) Join(field string, subitems []interface{}, context int } ``` +### Subqueries (nested queries) + +A condition could be applied to result of another query (subquery) included into the current query. +The condition may either be on resulting rows of the subquery: + +```go +query := db.Query("main_ns"). + WhereQuery(db.Query("second_ns").Select("id").Where("age", reindexer.GE, 18), reindexer.GE, 100) +``` +or between a field of main query's namespace and result of the subquery: +```go +query := db.Query("main_ns"). + Where("id", reindexer.EQ, db.Query("second_ns").Select("id").Where("age", reindexer.GE, 18)) +``` +Result of the subquery may either be a certain field pointed by `Select` method (in this case it must set the single field filter): +```go +query1 := db.Query("main_ns"). + WhereQuery(db.Query("second_ns").Select("id").Where("age", reindexer.GE, 18), reindexer.GE, 100) +query2 := db.Query("main_ns"). + Where("id", reindexer.EQ, db.Query("second_ns").Select("id").Where("age", reindexer.GE, 18)) +``` +or count of items satisfying to the subquery required by `ReqTotal` or `CachedTotal` methods: +```go +query1 := db.Query("main_ns"). + WhereQuery(db.Query("second_ns").Where("age", reindexer.GE, 18).ReqTotal(), reindexer.GE, 100) +query2 := db.Query("main_ns"). + Where("id", reindexer.EQ, db.Query("second_ns").Where("age", reindexer.GE, 18).CachedTotal()) +``` +or aggregation: +```go +query1 := db.Query("main_ns"). + WhereQuery(db.Query("second_ns").Where("age", reindexer.GE, 18).AggregateMax("age"), reindexer.GE, 33) +query2 := db.Query("main_ns"). + Where("age", reindexer.GE, db.Query("second_ns").Where("age", reindexer.GE, 18).AggregateAvg("age")) +``` +`Min`, `Max`, `Avg`, `Sum`, `Count` and `CountCached` aggregations are allowed only. Subquery can not contain multiple aggregations at the same time. + +Subquery can be applied to the same namespace or to the another one. + +Subquery can not contain another subquery, join or merge. + +If you want to check if at least one of the items is satisfying to the subqueries, you may use `ANY` or `EMPTY` condition: +```go +query1 := db.Query("main_ns"). + WhereQuery(db.Query("second_ns").Where("age", reindexer.GE, 18), reindexer.ANY, nil) +query2 := db.Query("main_ns"). + WhereQuery(db.Query("second_ns").Where("age", reindexer.LE, 18), reindexer.EMPTY, nil) +``` + ### Complex Primary Keys and Composite Indexes A Document can have multiple fields as a primary key. To enable this feature add composite index to struct. @@ -1199,8 +1253,6 @@ func (item *Item) DeepCopy () interface {} { } ``` -There are available code generation tool [gencopy](../gencopy), which can automatically generate DeepCopy interface for structs. - #### Get shared objects from object cache (USE WITH CAUTION) To speed up queries and do not allocate new objects per each query it is possible ask query return objects directly from object cache. For enable this behavior, call `AllowUnsafe(true)` on `Iterator`. @@ -1377,7 +1429,7 @@ go func() { pprof -symbolize remote http://localhost:6060/debug/pprof/profile?seconds=10 ``` -#### Known issues +#### Known profiling issues Due to internal Golang's specific it's not recommended to try to get CPU and heap profiles simultaneously, because it may cause deadlock inside the profiler. @@ -1429,9 +1481,11 @@ For install run: pip3 install pyreindexer ``` -https://github.com/Restream/reindexer-py -https://pypi.org/project/pyreindexer/ -Python version >=3.6 is required). +URLs: +- https://github.com/Restream/reindexer-py +- https://pypi.org/project/pyreindexer/ + +Python version >=3.6 is required. ### Reindexer for Java @@ -1443,31 +1497,33 @@ Reindexer for java is official connector, and maintained by Reindexer's team. It For enable builtin mode support reindexer-dev (version >= 3.1.0) should be installed. See [installation instructions](cpp_src/readme.md#Installation) for details. For install reindexer to Java or Kotlin project add the following lines to maven project file -```` +``` com.github.restream rx-connector [LATEST_VERSION] -```` -https://github.com/Restream/reindexer-java +``` +URL: https://github.com/Restream/reindexer-java + Note: Java version >= 1.8 is required. + #### Spring wrapper Spring wrapper for Java-connector: https://github.com/evgeniycheban/spring-data-reindexer ### 3rd party open source connectors #### PHP -https://github.com/Smolevich/reindexer-client +URL: https://github.com/Smolevich/reindexer-client - *Support modes:* standalone only - *API Used:* HTTP REST API - *Dependency on reindexer library (reindexer-dev package):* no #### Rust -https://github.com/coinrust/reindexer-rs +URL: https://github.com/coinrust/reindexer-rs - *Support modes:* standalone, builtin - *API Used:* binary ABI, cproto - *Dependency on reindexer library (reindexer-dev package):* yes #### .NET -https://github.com/oruchreis/ReindexerNet +URL: https://github.com/oruchreis/ReindexerNet - *Support modes:* builtin - *API Used:* binary ABI - *Dependency on reindexer library (reindexer-dev package):* yes @@ -1492,4 +1548,3 @@ Landing: https://reindexer.io/ Packages repo: https://repo.reindexer.io/ More documentation (RU): https://reindexer.io/reindexer-docs/ - diff --git a/reindexer.go b/reindexer.go index d843e419a..06a7cff07 100644 --- a/reindexer.go +++ b/reindexer.go @@ -48,12 +48,14 @@ const ( // Aggregation funcs const ( - AggAvg = bindings.AggAvg - AggSum = bindings.AggSum - AggFacet = bindings.AggFacet - AggMin = bindings.AggMin - AggMax = bindings.AggMax - AggDistinct = bindings.AggDistinct + AggAvg = bindings.AggAvg + AggSum = bindings.AggSum + AggFacet = bindings.AggFacet + AggMin = bindings.AggMin + AggMax = bindings.AggMax + AggDistinct = bindings.AggDistinct + AggCount = bindings.AggCount + AggCountCached = bindings.AggCountCached ) // Reindexer error codes @@ -74,6 +76,7 @@ const ( ErrCodeNotFound = bindings.ErrNotFound ErrCodeStateInvalidated = bindings.ErrStateInvalidated ErrCodeTimeout = bindings.ErrTimeout + ErrCodeStrictMode = bindings.ErrStrictMode ) // Reindexer The reindxer state struct @@ -127,7 +130,6 @@ var ( errNsNotFound = bindings.NewError("rq: Namespace is not found", ErrCodeNotFound) errNsExists = bindings.NewError("rq: Namespace is already exists", ErrCodeParams) errInvalidReflection = bindings.NewError("rq: Invalid reflection type of index", ErrCodeParams) - errStorageNotEnabled = bindings.NewError("rq: Storage is not enabled, can't save", ErrCodeLogic) errIteratorNotReady = bindings.NewError("rq: Iterator not ready. Next() must be called before", ErrCodeLogic) errJoinUnexpectedField = bindings.NewError("rq: Unexpected join field", ErrCodeParams) ErrEmptyNamespace = bindings.NewError("rq: empty namespace name", ErrCodeParams) diff --git a/reindexer_impl.go b/reindexer_impl.go index 1b57e41e6..045934334 100644 --- a/reindexer_impl.go +++ b/reindexer_impl.go @@ -37,13 +37,14 @@ type reindexerNamespace struct { // reindexerImpl The reindxer state struct type reindexerImpl struct { - lock sync.RWMutex - ns map[string]*reindexerNamespace - storagePath string - binding bindings.RawBinding - debugLevels map[string]int - nsHashCounter int - status error + lock sync.RWMutex + ns map[string]*reindexerNamespace + storagePath string + binding bindings.RawBinding + debugLevels map[string]int + nsHashCounter int + strictJoinHandlers bool + status error promMetrics *reindexerPrometheusMetrics @@ -136,7 +137,6 @@ func newReindexImpl(dsn interface{}, options ...interface{}) *reindexerImpl { if v.EnablePrometheusMetrics { rx.promMetrics = newPrometheusMetrics(dsnParsed) } - case bindings.OptionOpenTelemetry: if v.EnableTracing { rx.otelTracer = otel.Tracer( @@ -147,6 +147,8 @@ func newReindexImpl(dsn interface{}, options ...interface{}) *reindexerImpl { otelattr.String("rx.dsn", dsnString(dsnParsed)), } } + case bindings.OptionStrictJoinHandlers: + rx.strictJoinHandlers = v.EnableStrictJoinHandlers } } @@ -201,7 +203,7 @@ func (db *reindexerImpl) getStatus(ctx context.Context) bindings.Status { // setLogger sets logger interface for output reindexer logs func (db *reindexerImpl) setLogger(log Logger) { - if log != nil { + if log != nil && (reflect.ValueOf(log).Kind() != reflect.Ptr || !reflect.ValueOf(log).IsNil()) { db.binding.EnableLogger(log) } else { db.binding.DisableLogger() @@ -421,8 +423,7 @@ func (db *reindexerImpl) renameNamespace(ctx context.Context, srcNsName string, defer prometheus.NewTimer(db.promMetrics.clientCallsLatency.WithLabelValues("RenameNamespace", srcNsName)).ObserveDuration() } - err := db.binding.RenameNamespace(ctx, srcNsName, dstNsName) - if err != nil { + if err := db.binding.RenameNamespace(ctx, srcNsName, dstNsName); err != nil { return err } db.lock.Lock() @@ -435,7 +436,7 @@ func (db *reindexerImpl) renameNamespace(ctx context.Context, srcNsName string, } else { delete(db.ns, dstNsName) } - return err + return nil } // closeNamespace - close namespace, but keep storage @@ -826,7 +827,7 @@ func (db *reindexerImpl) addFilterDSL(filter *dsl.Filter, q *Query) error { func (db *reindexerImpl) addJoinedDSL(joined *dsl.JoinQuery, resultField string, q *Query) error { if joined.Namespace == "" { - return ErrEmptyNamespace + return bindings.NewError("rq: empty namespace name in joined query", ErrCodeParams) } jq := db.query(joined.Namespace).Offset(joined.Offset) @@ -836,9 +837,7 @@ func (db *reindexerImpl) addJoinedDSL(joined *dsl.JoinQuery, resultField string, if joined.Sort.Field != "" { jq.Sort(joined.Sort.Field, joined.Sort.Desc, joined.Sort.Values...) } - - _, err := db.handleFiltersDSL(joined.Filters, nil, jq) - if err != nil { + if _, err := db.handleFiltersDSL(joined.Filters, nil, jq); err != nil { return err } @@ -882,8 +881,99 @@ func (db *reindexerImpl) addJoinedDSL(joined *dsl.JoinQuery, resultField string, return nil } +func (db *reindexerImpl) addSubqueryDSL(filter *dsl.Filter, q *Query) error { + if filter.SubQ.Namespace == "" { + return bindings.NewError("rq: empty namespace name in subquery", ErrCodeParams) + } + if filter.Field != "" && filter.Value != nil { + return bindings.NewError("rq: filter: both field name and value in filter with subquery are not empty (expecting exactly one of them)", ErrCodeParams) + } + cond, err := GetCondType(filter.Cond) + if err != nil { + return err + } + if len(filter.SubQ.SelectFilter) > 1 { + return bindings.NewError(fmt.Sprintf("rq: subquery can not have multiple select_filter's: %v", filter.SubQ.SelectFilter), ErrCodeParams) + } + if cond == EMPTY || cond == ANY { + if filter.SubQ.Limit > 0 { + return bindings.NewError("rq: filter: subquery with condition Any or Empty can not contain limit", ErrCodeParams) + } + if filter.SubQ.Offset > 0 { + return bindings.NewError("rq: filter: subquery with condition Any or Empty can not contain offset", ErrCodeParams) + } + if filter.SubQ.ReqTotal { + return bindings.NewError("rq: filter: subquery with condition Any or Empty can not contain ReqTotal", ErrCodeParams) + } + if len(filter.SubQ.Aggregations) > 0 { + return bindings.NewError("rq: filter: subquery with condition Any or Empty can not contain aggregations", ErrCodeParams) + } + if len(filter.SubQ.SelectFilter) > 0 { + return bindings.NewError("rq: filter: subquery with condition Any or Empty can not contain select filter", ErrCodeParams) + } + } else { + for _, agg := range filter.SubQ.Aggregations { + switch strings.ToLower(agg.AggType) { + case dsl.AggSum, dsl.AggAvg, dsl.AggMin, dsl.AggMax, dsl.AggCount, dsl.AggCountCached: + // Skip + default: + return bindings.NewError(fmt.Sprintf("rq: filter: unsupported aggregation for subquery: '%s'", agg.AggType), ErrCodeParams) + } + } + totalAggs := len(filter.SubQ.Aggregations) + if filter.SubQ.ReqTotal { + totalAggs++ + } + if totalAggs > 1 { + return bindings.NewError("rq: filter: subquery can not contain more than 1 aggregation / count request", ErrCodeParams) + } + if totalAggs == 1 && len(filter.SubQ.SelectFilter) > 0 { + return bindings.NewError("rq: subquery can not have select_filter and aggregations at the same time", ErrCodeParams) + } + if totalAggs == 0 && len(filter.SubQ.SelectFilter) != 1 { + return bindings.NewError(fmt.Sprintf("rq: subquery with Cond '%s' and without aggregations must have exactly 1 select_filter", filter.Cond), ErrCodeParams) + } + } + + sq := db.query(filter.SubQ.Namespace).Offset(filter.SubQ.Offset).Select(filter.SubQ.SelectFilter...) + if filter.SubQ.Limit > 0 { + sq.Limit(filter.SubQ.Limit) + } + if filter.SubQ.ReqTotal { + sq.ReqTotal() + } + if filter.SubQ.Sort.Field != "" { + sq.Sort(filter.SubQ.Sort.Field, filter.SubQ.Sort.Desc, filter.SubQ.Sort.Values...) + } + if err = db.addAggregationsDSL(sq, filter.SubQ.Aggregations); err != nil { + return err + } + if _, err = db.handleFiltersDSL(filter.SubQ.Filters, nil, sq); err != nil { + return err + } + + if filter.Field != "" { + // Subquery with field + if cond == EMPTY || cond == ANY { + return bindings.NewError("rq: filter: subquery with condition Any or Empty can not have Field in the filter", ErrCodeParams) + } + q.Where(filter.Field, cond, sq) + } else { + if (cond == EMPTY || cond == ANY) && filter.Value != nil { + return bindings.NewError("rq: filter: subquery with condition Any or Empty can not have non-nil target Value", ErrCodeParams) + } + if cond != EMPTY && cond != ANY && filter.Value == nil { + return bindings.NewError(fmt.Sprintf("rq: filter: subquery with condition %v can not have nil target Value and empty field name", filter.Cond), ErrCodeParams) + } + // Subquery with explicit values + q.WhereQuery(sq, cond, filter.Value) + + } + return nil +} + func (db *reindexerImpl) handleFiltersDSL(filters []dsl.Filter, joinIDs *map[string]int, q *Query) (*Query, error) { - for fi, _ := range filters { + for fi := range filters { filter := &filters[fi] switch strings.ToLower(filters[fi].Op) { case "": @@ -895,18 +985,27 @@ func (db *reindexerImpl) handleFiltersDSL(filters []dsl.Filter, joinIDs *map[str case "not": q.Not() default: - return nil, bindings.NewError("rq: dsl filter op is invalid", ErrCodeParams) + return nil, bindings.NewError(fmt.Sprintf("rq: dsl filter op is invalid: '%s'", filters[fi].Op), ErrCodeParams) } if filter.Joined != nil { if joinIDs == nil { return nil, bindings.NewError("rq: nested join quieries are not supported", ErrCodeParams) } - if filter.Field != "" || filter.Cond != "" { + if filter.Field != "" { return nil, bindings.NewError("rq: dsl filter can not contain both 'field' and 'join_query' at the same time", ErrCodeParams) } + if filter.Cond != "" { + return nil, bindings.NewError("rq: dsl filter can not contain both 'cond' and 'join_query' at the same time", ErrCodeParams) + } + if filter.Value != nil { + return nil, bindings.NewError("rq: dsl filter can not contain both 'value' and 'join_query' at the same time", ErrCodeParams) + } if len(filter.Filters) != 0 { - return nil, bindings.NewError("rq: dsl filter can not contain both 'fielters' and 'join_query' at the same time", ErrCodeParams) + return nil, bindings.NewError("rq: dsl filter can not contain both 'filters' and 'join_query' at the same time", ErrCodeParams) + } + if filter.SubQ != nil { + return nil, bindings.NewError("rq: dsl filter can not contain both 'subquery' and 'join_query' at the same time", ErrCodeParams) } var joinedFieldName string @@ -917,33 +1016,76 @@ func (db *reindexerImpl) handleFiltersDSL(filters []dsl.Filter, joinIDs *map[str joinedFieldName = fmt.Sprintf("_dsl_joined_%s", filter.Joined.Namespace) (*joinIDs)[filter.Joined.Namespace] = 0 } - err := db.addJoinedDSL(filter.Joined, joinedFieldName, q) - if err != nil { + if err := db.addJoinedDSL(filter.Joined, joinedFieldName, q); err != nil { return nil, err } continue - } - - if len(filter.Filters) != 0 { + } else if len(filter.Filters) != 0 { if len(filter.Field) != 0 || len(filter.Cond) != 0 { return nil, bindings.NewError("rq: dsl filter can not contain both 'field' and 'filters' at the same time", ErrCodeParams) } + if filter.SubQ != nil { + return nil, bindings.NewError("rq: dsl filter can not contain both 'subquery' and 'filters' at the same time", ErrCodeParams) + } + if filter.Cond != "" { + return nil, bindings.NewError("rq: dsl filter can not contain both 'cond' and 'filters' at the same time", ErrCodeParams) + } + if filter.Value != nil { + return nil, bindings.NewError("rq: dsl filter can not contain both 'value' and 'filters' at the same time", ErrCodeParams) + } q.OpenBracket() - _, err := db.handleFiltersDSL(filter.Filters, joinIDs, q) - if err != nil { + if _, err := db.handleFiltersDSL(filter.Filters, joinIDs, q); err != nil { return nil, err } q.CloseBracket() continue + } else if filter.SubQ != nil { + if err := db.addSubqueryDSL(filter, q); err != nil { + return nil, err + } + continue } - err := db.addFilterDSL(filter, q) - if err != nil { + if err := db.addFilterDSL(filter, q); err != nil { return nil, err } } return q, nil } +func (db *reindexerImpl) addAggregationsDSL(q *Query, aggs []dsl.Aggregation) error { + for _, agg := range aggs { + if len(agg.Fields) == 0 { + return ErrEmptyAggFieldName + } + switch strings.ToLower(agg.AggType) { + case dsl.AggSum: + q.AggregateSum(agg.Fields[0]) + case dsl.AggAvg: + q.AggregateAvg(agg.Fields[0]) + case dsl.AggFacet: + aggReq := q.AggregateFacet(agg.Fields...).Limit(agg.Limit).Offset(agg.Offset) + for _, sort := range agg.Sort { + aggReq.Sort(sort.Field, sort.Desc) + } + case dsl.AggMin: + q.AggregateMin(agg.Fields[0]) + case dsl.AggMax: + q.AggregateMax(agg.Fields[0]) + case dsl.AggDistinct: + q.Distinct(agg.Fields[0]) + case dsl.AggCount: + if len(agg.Fields) == 1 && (agg.Fields[0] == "" || agg.Fields[0] == "*") { + q.ReqTotal() + } else { + q.ReqTotal(agg.Fields...) + } + default: + return bindings.NewError(fmt.Sprintf("rq: unsupported aggregation type: '%s'", agg.AggType), ErrCodeParams) + } + } + return nil +} + func (db *reindexerImpl) queryFrom(d *dsl.DSL) (*Query, error) { if d.Namespace == "" { return nil, ErrEmptyNamespace @@ -960,29 +1102,8 @@ func (db *reindexerImpl) queryFrom(d *dsl.DSL) (*Query, error) { q.Distinct(d.Distinct) } - for _, agg := range d.Aggregations { - if len(agg.Fields) == 0 { - return nil, ErrEmptyAggFieldName - } - switch agg.AggType { - case AggSum: - q.AggregateSum(agg.Fields[0]) - case AggAvg: - q.AggregateAvg(agg.Fields[0]) - case AggFacet: - aggReq := q.AggregateFacet(agg.Fields...).Limit(agg.Limit).Offset(agg.Offset) - for _, sort := range agg.Sort { - aggReq.Sort(sort.Field, sort.Desc) - } - case AggMin: - q.AggregateMin(agg.Fields[0]) - case AggMax: - q.AggregateMax(agg.Fields[0]) - case AggDistinct: - q.Distinct(agg.Fields[0]) - default: - return nil, ErrAggInvalid - } + if err := db.addAggregationsDSL(q, d.Aggregations); err != nil { + return nil, err } if d.Sort.Field != "" { diff --git a/test/builtinserver_test.go b/test/builtinserver_test.go index 978e23c6d..2b96c59b1 100644 --- a/test/builtinserver_test.go +++ b/test/builtinserver_test.go @@ -19,7 +19,7 @@ func TestBuiltinServer(t *testing.T) { cfg1 := config.DefaultServerConfig() cfg1.Net.HTTPAddr = "0:29088" cfg1.Net.RPCAddr = "0:26534" - cfg1.Storage.Path = "/tmp/rx_builtinserver_test1" + cfg1.Storage.Path = "/tmp/reindex_builtinserver_test1" os.RemoveAll(cfg1.Storage.Path) rx1 := reindexer.NewReindex("builtinserver://xxx", reindexer.WithServerConfig(time.Second*100, cfg1)) @@ -30,7 +30,7 @@ func TestBuiltinServer(t *testing.T) { cfg2 := config.DefaultServerConfig() cfg2.Net.HTTPAddr = "0:29089" cfg2.Net.RPCAddr = "0:26535" - cfg2.Storage.Path = "/tmp/rx_builtinserver_test2" + cfg2.Storage.Path = "/tmp/reindex_builtinserver_test2" os.RemoveAll(cfg2.Storage.Path) rx2 := reindexer.NewReindex("builtinserver://xxx", reindexer.WithServerConfig(time.Second*100, cfg2)) @@ -46,7 +46,7 @@ func TestBuiltinServer(t *testing.T) { cfg4 := config.DefaultServerConfig() cfg4.Net.HTTPAddr = "0:29090" cfg4.Net.RPCAddr = "0:26536" - cfg4.Storage.Path = "/tmp/rx_builtinserver_test4" + cfg4.Storage.Path = "/tmp/reindex_builtinserver_test4" cfg4.Net.UnixRPCAddr = "/tmp/reindexer_builtinserver_test.sock" os.RemoveAll(cfg4.Storage.Path) diff --git a/test/compatibility_test/compatibility_test.sh b/test/compatibility_test/compatibility_test.sh index 9300f0e77..31b893ff3 100755 --- a/test/compatibility_test/compatibility_test.sh +++ b/test/compatibility_test/compatibility_test.sh @@ -39,19 +39,19 @@ test_outdated_instance() { echo "====Master: ${master_cmd}" echo "====Slave: ${slave_cmd}" init_storages - ${master_cmd} --db "${master_db_path}" -l0 --serverlog=\"\" --corelog=\"\" --httplog=\"\" --rpclog=\"\" & + ${master_cmd} --db "${master_db_path}" -l0 --serverlog=\"reindexer_master_$3.1.log\" --corelog=\"reindexer_master_$3.1.log\" --httplog=\"\" --rpclog=\"\" & master_pid=$! sleep 4 go run ${script_dir}/filler.go --dsn "${master_dsn}/${db_name}" --offset 0 echo "====Force sync" - ${slave_cmd} --db "${slave_db_path}" -p 9089 -r 6535 -l0 --serverlog=\"\" --corelog=\"\" --httplog=\"\" --rpclog=\"\" & + ${slave_cmd} --db "${slave_db_path}" -p 9089 -r 6535 -l0 --serverlog=\"reindexer_slave_$3.1.log\" --corelog=\"reindexer_slave_$3.1.log\" --httplog=\"\" --rpclog=\"\" & slave_pid=$! sleep 5 kill $slave_pid wait $slave_pid go run ${script_dir}/filler.go --dsn "${master_dsn}/${db_name}" --offset 100 echo "====Sync by WAL" - ${slave_cmd} --db "${slave_db_path}" -p 9089 -r 6535 -l0 --serverlog=\"\" --corelog=\"\" --httplog=\"\" --rpclog=\"\" & + ${slave_cmd} --db "${slave_db_path}" -p 9089 -r 6535 -l0 --serverlog=\"reindexer_slave_$3.2.log\" --corelog=\"reindexer_slave_$3.2.log\" --httplog=\"\" --rpclog=\"\" & slave_pid=$! sleep 5 echo "====Online sync" @@ -71,8 +71,8 @@ echo "====Installing reindexer package====" echo "====URL: ${rpm_url}" yum install -y ${rpm_url} > /dev/null || true echo "====Checking outdated slave====" -test_outdated_instance "build/cpp_src/cmd/reindexer_server/reindexer_server" "reindexer_server" +test_outdated_instance "build/cpp_src/cmd/reindexer_server/reindexer_server" "reindexer_server" "1" echo "====Checking outdated master====" -test_outdated_instance "reindexer_server" "build/cpp_src/cmd/reindexer_server/reindexer_server" +test_outdated_instance "reindexer_server" "build/cpp_src/cmd/reindexer_server/reindexer_server" "2" clear_artifacts diff --git a/test/dsl_test.go b/test/dsl_test.go index 11284bd74..ae2740b19 100644 --- a/test/dsl_test.go +++ b/test/dsl_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/restream/reindexer/v3" "github.com/restream/reindexer/v3/dsl" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -30,6 +31,9 @@ func init() { tnamespaces["test_namespace_dsl_ft"] = TestDSLFtItem{} tnamespaces["test_namespace_dsl_joined_1"] = TestDSLJoinItem{} tnamespaces["test_namespace_dsl_joined_2"] = TestDSLJoinItem{} + + tnamespaces["test_namespace_dsl_2"] = TestDSLItem{} + tnamespaces["test_namespace_dsl_joined_3"] = TestDSLJoinItem{} } func newTestDSLItem(id int) interface{} { @@ -95,7 +99,7 @@ func getTesDSLFtItemsDescr(items []interface{}) []string { return resultDescr } -func getTesDSLJoinItemsIDs(items []interface{}) []int { +func getTestDSLItemsIDs(items []interface{}) []int { resultIDs := make([]int, len(items)) for i, v := range items { item := v.(*TestDSLItem) @@ -104,6 +108,40 @@ func getTesDSLJoinItemsIDs(items []interface{}) []int { return resultIDs } +func getTestDSLJoinItemsIDs(items []interface{}) []int { + resultIDs := make([]int, len(items)) + for i, v := range items { + item := v.(*TestDSLJoinItem) + resultIDs[i] = item.JID + } + return resultIDs +} + +func execDSLTwice(t *testing.T, testF func(*testing.T, *reindexer.Query), jsonDSL string) { + var marshaledJSON []byte + { + var dslQ dsl.DSL + err := json.Unmarshal([]byte(jsonDSL), &dslQ) + require.NoError(t, err) + q, err := DBD.QueryFrom(dslQ) + require.NoError(t, err) + require.NotNil(t, q) + testF(t, q) + marshaledJSON, err = json.Marshal(dslQ) + require.NoError(t, err) + } + + { + var dslQ dsl.DSL + err := json.Unmarshal(marshaledJSON, &dslQ) + require.NoError(t, err) + q, err := DBD.QueryFrom(dslQ) + require.NoError(t, err) + require.NotNil(t, q) + testF(t, q) + } +} + func TestDSLQueries(t *testing.T) { t.Parallel() @@ -256,6 +294,10 @@ func TestDSLQueries(t *testing.T) { require.NoError(t, err) require.NotNil(t, q) // No results validation here + + _, err = json.Marshal(dslQ) + require.NoError(t, err) + // No results validation here }) t.Run("dsl equality condition", func(t *testing.T) { @@ -288,16 +330,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{90, 91, 92, 93, 99} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{90, 91, 92, 93, 99} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl multiple conditions", func(t *testing.T) { @@ -338,16 +376,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{21, 93, 99} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{21, 93, 99} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl multiple conditions with brackets", func(t *testing.T) { @@ -393,16 +427,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{21, 92, 93, 99} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{21, 92, 93, 99} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl with req_total", func(t *testing.T) { @@ -425,22 +455,17 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - - it := q.MustExec() - require.NoError(t, it.Error()) - count := it.TotalCount() - assert.Equal(t, 10, count) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + count := it.TotalCount() + assert.Equal(t, 10, count) - items, err := it.FetchAll() - require.NoError(t, err) - expectedIDs := []int{2, 3, 4, 5, 6, 7, 8} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + items, err := it.FetchAll() + require.NoError(t, err) + expectedIDs := []int{2, 3, 4, 5, 6, 7, 8} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl with select_with_rank", func(t *testing.T) { @@ -462,22 +487,17 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - - it := q.MustExec() - require.NoError(t, it.Error()) - items, ranks, err := it.FetchAllWithRank() - require.NoError(t, err) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + items, ranks, err := it.FetchAllWithRank() + require.NoError(t, err) - expectedOrder := []string{"worm", "sword", "word"} - expectedRanks := []int{75, 75, 107} - require.Equal(t, expectedOrder, getTesDSLFtItemsDescr(items)) - require.Equal(t, expectedRanks, ranks) + expectedOrder := []string{"worm", "sword", "word"} + expectedRanks := []int{75, 75, 107} + require.Equal(t, expectedOrder, getTesDSLFtItemsDescr(items)) + require.Equal(t, expectedRanks, ranks) + }, jsonDSL) }) t.Run("dsl filter nil value (expecting filter's skip)", func(t *testing.T) { @@ -499,16 +519,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{21, 92, 93, 97, 99} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{21, 92, 93, 97, 99} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl with empty array filter returns all items", func(t *testing.T) { @@ -522,15 +538,11 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - require.Equal(t, allIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + require.Equal(t, allIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl with empty array filter and multiple conditions", func(t *testing.T) { @@ -550,16 +562,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{3} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{3} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) @@ -579,168 +587,10 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond[0])), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - _, err = q.Exec().FetchAll() - require.ErrorContains(t, err, fmt.Sprintf("The '%s' condition is suported only by 'sparse' or 'array' indexes", cond[1])) - } - }) - - t.Run("dsl invalid filter array values args", func(t *testing.T) { - for _, cond := range []string{"gt", "lt", "ge", "le"} { - for _, value := range []string{"[]", "[1,2]"} { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", - "sort": { - "field": "id" - }, - "filters": [ - { - "op": "AND", - "field": "id", - "cond": "%s", - "value": %s - } - ] - } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value)), &dslQ) - require.EqualError(t, err, fmt.Sprintf("filter value can not be array with 0 or multiple values for '%s' condition", cond)) - } - } - }) - - t.Run("dsl cant filter value has type object", func(t *testing.T) { - for _, cond := range []string{"gt", "lt", "ge", "le", "eq"} { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", - "sort": { - "field": "id" - }, - "filters": [ - { - "op": "AND", - "field": "id", - "cond": "%s", - "value": {} - } - ] - } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) - require.EqualError(t, err, "filter value can not be object") - } - }) - - t.Run("dsl filter value must be array for 'set', 'allset', 'range'", func(t *testing.T) { - for _, cond := range []string{"set", "allset", "range"} { - for _, value := range []string{"123", "\"abc\"", "{}", "true"} { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", - "sort": { - "field": "id" - }, - "filters": [ - { - "op": "AND", - "field": "id", - "cond": "%s", - "value": %s - } - ] - } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value)), &dslQ) - require.EqualError(t, err, fmt.Sprintf("filter expects array or null for '%s' condition", cond)) - } - } - }) - - t.Run("dsl filter value must be array with 2 elements for 'range'", func(t *testing.T) { - for _, value := range []string{"[1]", "[1,2,3]"} { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", - "sort": { - "field": "id" - }, - "filters": [ - { - "op": "AND", - "field": "id", - "cond": "range", - "value": %s - } - ] - } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, value)), &dslQ) - require.EqualError(t, err, "range argument array must has 2 elements") - } - }) - - t.Run("dsl invalid filter cond type", func(t *testing.T) { - for _, cond := range []string{"equal", "not", "1"} { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", - "filters": [ - { - "op": "AND", - "field": "id", - "cond": "%s", - "value": 1 - } - ] - } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) - require.EqualError(t, err, fmt.Sprintf("cond type '%s' not found", cond)) - } - }) - - t.Run("dsl filter value array must be homogeneous", func(t *testing.T) { - for _, cond := range []string{"eq", "set"} { - for _, value := range [][]string{ - {"true, \"abc\"", "bool"}, {"false, 2", "bool"}, - {"1, \"2\"", "int/float"}, {"1.5, false", "int/float"}, - {"\"abc\", {}", "string"}, {"\"1\", 2", "string"}, {"\"a\", [\"b\"]", "string"}, - } { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", - "filters": [ - { - "op": "AND", - "field": "id", - "cond": "%s", - "value": [%s] - } - ] - } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value[0])), &dslQ) - require.EqualError(t, err, fmt.Sprintf("array must be homogeneous (%s)", value[1])) - } + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + _, err := q.Exec().FetchAll() + require.ErrorContains(t, err, fmt.Sprintf("The '%s' condition is suported only by 'sparse' or 'array' indexes", cond[1])) + }, fmt.Sprintf(jsonDSL, cond[0])) } }) @@ -764,16 +614,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{1} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{1} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl single join", func(t *testing.T) { @@ -817,21 +663,17 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - it := q.MustExec() - require.NoError(t, it.Error()) - explain, err := it.GetExplainResults() - assert.NoError(t, err) - assert.NotNil(t, explain) - expectedIDs := []int{10, 12, 14} - items, err := it.FetchAll() - require.NoError(t, err) - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.NotNil(t, explain) + expectedIDs := []int{10, 12, 14} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl single left join", func(t *testing.T) { @@ -873,21 +715,17 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - it := q.MustExec() - require.NoError(t, it.Error()) - explain, err := it.GetExplainResults() - assert.NoError(t, err) - assert.NotNil(t, explain) - expectedIDs := []int{1, 10, 12, 14, 17, 19, 99} - items, err := it.FetchAll() - require.NoError(t, err) - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.NotNil(t, explain) + expectedIDs := []int{1, 10, 12, 14, 17, 19, 99} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl 2 joins", func(t *testing.T) { @@ -950,21 +788,17 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - it := q.MustExec() - require.NoError(t, it.Error()) - explain, err := it.GetExplainResults() - assert.NoError(t, err) - assert.Nil(t, explain) - expectedIDs := []int{90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 19, 18, 17, 16, 15} - items, err := it.FetchAll() - require.NoError(t, err) - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.Nil(t, explain) + expectedIDs := []int{90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 19, 18, 17, 16, 15} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl join equality condition", func(t *testing.T) { @@ -1033,16 +867,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{17, 83, 84, 85, 91, 93, 99} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{17, 83, 84, 85, 91, 93, 99} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl join set condition", func(t *testing.T) { @@ -1105,16 +935,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{17, 18, 83, 91, 93, 99} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{17, 18, 83, 91, 93, 99} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl join multiple conditions", func(t *testing.T) { @@ -1202,16 +1028,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{11, 12, 13, 14, 15, 16, 17, 80, 81, 90, 91, 92, 93} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{11, 12, 13, 14, 15, 16, 17, 80, 81, 90, 91, 92, 93} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl join multiple conditions and brackets", func(t *testing.T) { @@ -1279,16 +1101,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{85, 86, 87, 88, 97, 98} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{85, 86, 87, 88, 97, 98} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl join filter nil value", func(t *testing.T) { @@ -1326,16 +1144,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{10, 11, 19} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{10, 11, 19} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl join with empty array filter returns all items", func(t *testing.T) { @@ -1365,16 +1179,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{10, 11, 12, 13, 14, 15, 16, 17, 18, 19} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{10, 11, 12, 13, 14, 15, 16, 17, 18, 19} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) t.Run("dsl join with empty array filter and multiple conditions", func(t *testing.T) { @@ -1410,16 +1220,12 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{15, 16} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{15, 16} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) @@ -1455,171 +1261,1475 @@ func TestDSLQueries(t *testing.T) { } ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond[0])), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - _, err = q.Exec().FetchAll() - require.ErrorContains(t, err, fmt.Sprintf("The '%s' condition is suported only by 'sparse' or 'array' indexes", cond[1])) + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + _, err := q.Exec().FetchAll() + require.ErrorContains(t, err, fmt.Sprintf("The '%s' condition is suported only by 'sparse' or 'array' indexes", cond[1])) + }, fmt.Sprintf(jsonDSL, cond[0])) } }) - t.Run("dsl join invalid filter array values args", func(t *testing.T) { - for _, cond := range []string{"gt", "lt", "ge", "le"} { - for _, value := range []string{"[]", "[1,2]"} { - const jsonDSL = ` + t.Run("dsl join with repeated fields: the next field overrides the previous one", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl_joined_1", + "namespace": "test_namespace_dsl", + "sort": { + "field": "none", + "field": "id" + }, + "filters": [ { - "namespace": "test_namespace_dsl", - "sort": { - "field": "id" - }, - "filters": [ - { - "op": "AND", - "join_query": { - "type": "inner", - "namespace": "test_namespace_dsl_joined_2", - "filters": [ - { - "op": "AND", - "field": "jid", - "cond": "%s", - "value": %s - } - ], - "on": [ - { - "left_field": "id", - "right_field": "jid", - "cond": "EQ" - } - ] + "op": "AND", + "join_query": { + "type": "left", + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "range", + "cond": "eq", + "value": 14, + "value": [15,16,17] } - } - ] + ], + "on": [ + { + "left_field": "id", + "right_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value)), &dslQ) - require.EqualError(t, err, fmt.Sprintf("filter value can not be array with 0 or multiple values for '%s' condition", cond)) - } + ] } - }) - - t.Run("dsl join cant filter value has type object", func(t *testing.T) { - for _, cond := range []string{"gt", "lt", "ge", "le", "eq"} { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", - "sort": { - "field": "id" - }, - "filters": [ - { - "op": "AND", - "join_query": { - "type": "inner", - "namespace": "test_namespace_dsl_joined_2", - "filters": [ - { - "op": "AND", - "field": "jid", - "cond": "%s", - "value": {} - } - ], - "on": [ - { - "left_field": "id", - "right_field": "jid", - "cond": "EQ" - } - ] - } - } - ] - } - ` + ` - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) - require.EqualError(t, err, "filter value can not be object") - } + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{15, 16, 17} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) - t.Run("dsl join filter value must be array for 'set', 'allset', 'range'", func(t *testing.T) { - for _, cond := range []string{"set", "allset", "range"} { - for _, value := range []string{"123", "\"abc\"", "{}", "true"} { - const jsonDSL = ` + t.Run("dsl forsed sort", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id", + "values": [98, 99] + }, + "filters": [ { - "namespace": "test_namespace_dsl", - "sort": { - "field": "id" - }, - "filters": [ - { - "op": "AND", - "join_query": { - "type": "inner", - "namespace": "test_namespace_dsl_joined_2", - "filters": [ - { - "op": "AND", - "field": "jid", - "cond": "%s", - "value": %s - } - ], - "on": [ - { - "left_field": "id", - "right_field": "jid", - "cond": "EQ" - } - ] - } - } - ] + "field": "id", + "cond": "ge", + "value": 95 } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value)), &dslQ) - require.EqualError(t, err, fmt.Sprintf("filter expects array or null for '%s' condition", cond)) - } + ] } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{98, 99, 95, 96, 97} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) }) - t.Run("dsl join filter value must be array with 2 elements for 'range'", func(t *testing.T) { - for _, value := range []string{"[1]", "[1,2,3]"} { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", + t.Run("cant dsl sort with expression", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id+2" + }, + "filters": [] + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + _, err := q.Exec().FetchAll() + require.ErrorContains(t, err, "Current query strict mode allows sort by existing fields only. "+ + "There are no fields with name 'id+2' in namespace 'test_namespace_dsl'") + }, jsonDSL) + }) + + t.Run("dsl join with sort", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "test_namespace_dsl_joined_2.jid", + "desc": false + }, + "explain": true, + "filters": [ + { + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "set", + "value": [11, 19, 13, 14, 10] + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + } + ] + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.NotNil(t, explain) + expectedIDs := []int{10, 11, 13, 14, 19} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) + }) + + t.Run("dsl single subquery", func(t *testing.T) { + // Using subquery the same way as join here + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id", + "desc": false + }, + "explain": true, + "filters": [ + { + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "range", + "value": [10,15] + } + ], + "select_filter": ["jid"] + } + }, + { + "field": "id", + "cond": "set", + "value": [ + 1,10,12,14,17,19,99 + ] + } + ] + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.NotNil(t, explain) + expectedIDs := []int{10, 12, 14} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) + }) + + t.Run("dsl single subquery with count", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl_joined_1", + "sort": { + "field": "jid", + "desc": false + }, + "explain": true, + "filters": [ + { + "field": "jid", + "cond": "GT", + "subquery": { + "namespace": "test_namespace_dsl", + "req_total": true + } + } + ] + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.NotNil(t, explain) + expectedIDs := []int{101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLJoinItemsIDs(items)) + }, jsonDSL) + }) + + t.Run("dsl single subquery with max aggregation", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl_joined_1", + "sort": { + "field": "jid", + "desc": false + }, + "explain": true, + "filters": [ + { + "field": "jid", + "cond": "GT", + "subquery": { + "namespace": "test_namespace_dsl", + "aggregations": [ + { + "type": "max", + "fields": [ "id" ] + } + ] + } + } + ] + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.NotNil(t, explain) + expectedIDs := []int{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLJoinItemsIDs(items)) + }, jsonDSL) + }) + + t.Run("dsl single join with always true subqueries", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id", + "desc": false + }, + "explain": true, + "filters": [ + { + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "range", + "value": [10,15] + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + }, + { + "field": "id", + "cond": "set", + "value": [ + 1,10,12,14,17,19,99 + ] + }, + { + "subquery": { + "namespace": "test_namespace_dsl_joined_1" + }, + "cond": "any" + }, + { + "subquery": { + "namespace": "test_namespace_dsl_joined_1", + "req_total": true + }, + "cond": "gt", + "value": [5] + } + ] + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.NotNil(t, explain) + expectedIDs := []int{10, 12, 14} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) + }) + + t.Run("dsl single join with always false subqueries", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id", + "desc": false + }, + "explain": true, + "filters": [ + { + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "range", + "value": [10,15] + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + }, + { + "field": "id", + "cond": "set", + "value": [ + 1,10,12,14,17,19,99 + ] + }, + { + "subquery": { + "namespace": "test_namespace_dsl_joined_1" + }, + "cond": "empty" + }, + { + "op": "OR", + "subquery": { + "namespace": "test_namespace_dsl_joined_1", + "req_total": true + }, + "cond": "le", + "value": [5] + } + ] + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.NotNil(t, explain) + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, []int{}, getTestDSLItemsIDs(items)) + }, jsonDSL) + }) + + t.Run("dsl 2 subqueries", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id", + "desc": true + }, + "filters": [ + { + "op": "AND", + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_1", + "limit": 1, + "offset": 0, + "select_filter": [ + "jid" + ], + "sort": { + "field": "jid", + "desc": false + } + } + }, + { + "op": "OR", + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "limit": 10, + "offset": 0, + "filters": [ + { + "field": "jid", + "cond": "ge", + "value": [15] + } + ], + "sort": { + "field": "jid", + "desc": true + }, + "select_filter": [ "jid" ] + } + }, + { + "op": "Not", + "field": "id", + "cond": "gt", + "value": [ + 90 + ] + } + ] + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + it := q.MustExec() + require.NoError(t, it.Error()) + explain, err := it.GetExplainResults() + assert.NoError(t, err) + assert.Nil(t, explain) + expectedIDs := []int{80, 19, 18, 17, 16, 15} + items, err := it.FetchAll() + require.NoError(t, err) + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) + }) +} + +func TestDSLQueriesParsingErrors(t *testing.T) { + t.Parallel() + + fillTestDSLItems(t, "test_namespace_dsl_2", 0, 100) + fillTestDSLJoinItems(t, "test_namespace_dsl_joined_3", 10, 10) + + t.Run("dsl unsupported fields will be ignored on unmarshaling with strict mode disabled", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl_2", + "sort": { + "field": "id" + }, + "filters": [ + { + "field": "id", + "cond": "set", + "value": [1,9,15,11,14], + "some_unsupported_0": true + }, + { + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_3", + "filters": [ + { + "field": "jid", + "cond": "range", + "value": [11,15] + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ], + "some_unsupported_1": "abc" + } + } + ], + "merge_queries": [ + { + "namespace": "test_namespace_dsl_joined_3", + "type": "select", + "filters": [ + { + "op": "And", + "field": "id", + "cond": "eq", + "value": [18] + } + ] + } + ], + "type": "select", + "select_functions": [ + "id = highlight(<,>)" + ], + "select_filter": ["age"], + "strict_mode": "rrr", + "some_unsupported_2": 123 + } + ` + + execDSLTwice(t, func(t *testing.T, q *reindexer.Query) { + items, err := q.MustExec().FetchAll() + require.NoError(t, err) + expectedIDs := []int{11, 14, 15} + require.Equal(t, expectedIDs, getTestDSLItemsIDs(items)) + }, jsonDSL) + }) + + t.Run("dsl unsupported fields will cause an error on unmarshaling with dsl strict mode enabled", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl_2", + "sort": { + "field": "id" + }, + "filters": [ + { + "field": "id", + "cond": "set", + "value": [1,9,15,11,14], + "some_unsupported_0": true + }, + { + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_3", + "filters": [ + { + "field": "jid", + "cond": "range", + "value": [11,15] + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ], + "some_unsupported_1": "abc" + } + } + ], + "merge_queries": [ + { + "namespace": "test_namespace_dsl_joined_3", + "type": "select", + "filters": [ + { + "op": "And", + "field": "id", + "cond": "eq", + "value": [18] + } + ] + } + ], + "type": "select", + "select_functions": [ + "id = highlight(<,>)" + ], + "select_filter": ["age"], + "strict_mode": "rrr", + "some_unsupported_2": 123 + } + ` + + dsl.EnabeStrictMode() + defer dsl.DisableStrictMode() + var dslQ dsl.DSL + err := json.Unmarshal([]byte(jsonDSL), &dslQ) + require.EqualError(t, err, `json: unknown field "some_unsupported_0"`) + }) + + t.Run("dsl unsupported fields will cause an error on DecodeJSON with dsl strict mode enabled", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "some_unsupported_0": 123, + "filters": [ + { + "field": "id", + "cond": "set", + "value": [1,9,15,11,14] + } + ] + } + ` + + dsl.EnabeStrictMode() + defer dsl.DisableStrictMode() + dslQ, err := dsl.DecodeJSON([]byte(jsonDSL)) + require.EqualError(t, err, `json: unknown field "some_unsupported_0"`) + require.Nil(t, dslQ) + }) + + t.Run("dsl invalid filter array values args", func(t *testing.T) { + for _, cond := range []string{"gt", "lt", "ge", "le"} { + for _, value := range []string{"[]", "[1,2]"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id" + }, + "filters": [ + { + "op": "AND", + "field": "id", + "cond": "%s", + "value": %s + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value)), &dslQ) + require.EqualError(t, err, fmt.Sprintf("filter value can not be array with 0 or multiple values for '%s' condition", cond)) + } + } + }) + + t.Run("dsl cant filter value has type object", func(t *testing.T) { + for _, cond := range []string{"gt", "lt", "ge", "le", "eq"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id" + }, + "filters": [ + { + "op": "AND", + "field": "id", + "cond": "%s", + "value": {} + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) + require.EqualError(t, err, "filter value can not be object") + } + }) + + t.Run("dsl filter value must be array for 'set', 'allset', 'range'", func(t *testing.T) { + for _, cond := range []string{"set", "allset", "range"} { + for _, value := range []string{"123", "\"abc\"", "{}", "true"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id" + }, + "filters": [ + { + "op": "AND", + "field": "id", + "cond": "%s", + "value": %s + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value)), &dslQ) + require.EqualError(t, err, fmt.Sprintf("filter expects array or null for '%s' condition", cond)) + } + } + }) + + t.Run("dsl filter value must be array with 2 elements for 'range'", func(t *testing.T) { + for _, value := range []string{"[1]", "[1,2,3]"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id" + }, + "filters": [ + { + "op": "AND", + "field": "id", + "cond": "range", + "value": %s + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, value)), &dslQ) + require.EqualError(t, err, "range argument array must has 2 elements") + } + }) + + t.Run("dsl invalid filter cond type", func(t *testing.T) { + for _, cond := range []string{"equal", "not", "1"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "op": "AND", + "field": "id", + "cond": "%s", + "value": 1 + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) + require.EqualError(t, err, fmt.Sprintf("cond type '%s' not found", cond)) + } + }) + + t.Run("dsl filter value array must be homogeneous", func(t *testing.T) { + for _, cond := range []string{"eq", "set"} { + for _, value := range [][]string{ + {"true, \"abc\"", "bool"}, {"false, 2", "bool"}, + {"1, \"2\"", "int/float"}, {"1.5, false", "int/float"}, + {"\"abc\", {}", "string"}, {"\"1\", 2", "string"}, {"\"a\", [\"b\"]", "string"}, + } { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "op": "AND", + "field": "id", + "cond": "%s", + "value": [%s] + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value[0])), &dslQ) + require.EqualError(t, err, fmt.Sprintf("array must be homogeneous (%s)", value[1])) + } + } + }) + + t.Run("dsl join invalid filter array values args", func(t *testing.T) { + for _, cond := range []string{"gt", "lt", "ge", "le"} { + for _, value := range []string{"[]", "[1,2]"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id" + }, + "filters": [ + { + "op": "AND", + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "op": "AND", + "field": "jid", + "cond": "%s", + "value": %s + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value)), &dslQ) + require.EqualError(t, err, fmt.Sprintf("filter value can not be array with 0 or multiple values for '%s' condition", cond)) + } + } + }) + + t.Run("dsl join cant filter value has type object", func(t *testing.T) { + for _, cond := range []string{"gt", "lt", "ge", "le", "eq"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id" + }, + "filters": [ + { + "op": "AND", + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "op": "AND", + "field": "jid", + "cond": "%s", + "value": {} + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) + require.EqualError(t, err, "filter value can not be object") + } + }) + + t.Run("dsl join filter value must be array for 'set', 'allset', 'range'", func(t *testing.T) { + for _, cond := range []string{"set", "allset", "range"} { + for _, value := range []string{"123", "\"abc\"", "{}", "true"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "sort": { + "field": "id" + }, + "filters": [ + { + "op": "AND", + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "op": "AND", + "field": "jid", + "cond": "%s", + "value": %s + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value)), &dslQ) + require.EqualError(t, err, fmt.Sprintf("filter expects array or null for '%s' condition", cond)) + } + } + }) + + t.Run("dsl join filter value must be array with 2 elements for 'range'", func(t *testing.T) { + for _, value := range []string{"[1]", "[1,2,3]"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", "sort": { "field": "id" }, "filters": [ { - "op": "AND", - "join_query": { - "type": "inner", + "op": "AND", + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "op": "AND", + "field": "jid", + "cond": "range", + "value": %s + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, value)), &dslQ) + require.EqualError(t, err, "range argument array must has 2 elements") + } + }) + + t.Run("dsl join invalid filter cond type", func(t *testing.T) { + for _, cond := range []string{"equal", "not", "1"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "op": "AND", + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "op": "AND", + "field": "jid", + "cond": "%s", + "value": 1 + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) + require.EqualError(t, err, fmt.Sprintf("cond type '%s' not found", cond)) + } + }) + + t.Run("dsl join filter value array must be homogeneous", func(t *testing.T) { + for _, cond := range []string{"eq", "set"} { + for _, value := range [][]string{ + {"true, \"abc\"", "bool"}, {"false, 2", "bool"}, + {"1, \"2\"", "int/float"}, {"1.5, false", "int/float"}, + {"\"abc\", {}", "string"}, {"\"1\", 2", "string"}, {"\"a\", [\"b\"]", "string"}, + } { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "op": "AND", + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "op": "AND", + "field": "jid", + "cond": "%s", + "value": [%s] + } + ], + "on": [ + { + "left_field": "id", + "right_field": "jid", + "cond": "EQ" + } + ] + } + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value[0])), &dslQ) + require.EqualError(t, err, fmt.Sprintf("array must be homogeneous (%s)", value[1])) + } + } + }) + + t.Run("dsl filters can not be without 'cond', 'field' and 'value'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "SET", + "value": [10,15] + } + ], + "select_filter": ["jid"] + } + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(jsonDSL), &dslQ) + require.EqualError(t, err, "cond type '' not found") + }) + + t.Run("dsl filter can not contain 'cond' without 'field', 'value' or 'subquery'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "cond": "EQ", + "filters": [ + { + "field": "jid", + "cond": "EQ", + "value": [10] + } + ] + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(jsonDSL), &dslQ) + require.EqualError(t, err, "unable to use Cond without Field/Subquery/Value") + }) + + t.Run("dsl filter can not contain 'value' without 'field' or 'subquery'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "value": [1], + "filters": [ + { + "field": "jid", + "cond": "EQ", + "value": [10] + } + ] + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(jsonDSL), &dslQ) + require.EqualError(t, err, "unable to use Value without Field/Subquery") + }) + + t.Run("dsl subquery can not be with any/empty 'cond' and not empty 'value'", func(t *testing.T) { + for _, cond := range []string{"any", "empty"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "value": [1], + "cond": "%s", + "subquery": { "namespace": "test_namespace_dsl_joined_2", "filters": [ { - "op": "AND", - "field": "jid", - "cond": "range", - "value": %s + "field": "jid", + "cond": "EQ", + "value": [10] + } + ] + } + } + ] + } + ` + + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) + require.EqualError(t, err, fmt.Sprintf("filter expects no arguments or null for '%s' condition", cond)) + } + }) + + t.Run("dsl subquery can not contain prohibited fields", func(t *testing.T) { + for _, field := range [][]string{ + {"select_functions", `["description = highlight(<,>)"]`, "select_functions"}, + {"update_fields", `[{"type": "value", "name": "id", "values": [1]}]`, "update_fields"}, + {"drop_fields", `["id"]`, "drop_fields"}, + {"select_with_rank", "true", "select_with_rank"}, + {"type", `"update"`, "type"}, + } { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "value": [""], + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_ft", + "select_filter": ["description"], + "%s": %s + } + } + ] + } + ` + + dsl.EnabeStrictMode() + defer dsl.DisableStrictMode() + var dslQ dsl.DSL + err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, field[0], field[1])), &dslQ) + require.EqualError(t, err, fmt.Sprintf(`json: unknown field "%s"`, field[2])) + } + }) + + t.Run("dsl subquery can not contain merge", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_1", + "select_filter": ["jid"], + "merge_queries": [ + { + "namespace": "test_namespace_dsl_joined_2", + "select_filter": ["jid"], + "filters": [ + { + "field": "id", + "cond": "EQ", + "value": [10] + } + ] + } + ] + } + } + ] + } + ` + + dsl.EnabeStrictMode() + defer dsl.DisableStrictMode() + var dslQ dsl.DSL + err := json.Unmarshal([]byte(jsonDSL), &dslQ) + require.EqualError(t, err, `json: unknown field "merge_queries"`) + }) +} + +func checkErrorQueryFrom(t *testing.T, jsonDSL string, description string) { + var dslQ dsl.DSL + err := json.Unmarshal([]byte(jsonDSL), &dslQ) + require.NoError(t, err) + _, err = DBD.QueryFrom(dslQ) + require.EqualError(t, err, description) +} + +func TestCreateDSLQueriesErrors(t *testing.T) { + t.Parallel() + + t.Run("dsl subquery can not be without 'namespace'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "cond": "EQ", + "subquery": { + "filters": [ + { + "field": "jid", + "cond": "SET", + "value": [10,15] + } + ], + "select_filter": ["jid"] + } + } + ] + } + ` + checkErrorQueryFrom(t, jsonDSL, "rq: empty namespace name in subquery") + }) + + t.Run("dsl filter for subquery can not be without 'field' and 'value'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "SET", + "value": [10,15] + } + ], + "select_filter": ["jid"] + } + } + ] + } + ` + checkErrorQueryFrom(t, jsonDSL, + "rq: filter: subquery with condition EQ can not have nil target Value and empty field name") + }) + + t.Run("dsl filter for subquery can not be with both 'field' and 'value'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "value": [1,2], + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "SET", + "value": [10,15] + } + ], + "select_filter": ["jid"] + } + } + ] + } + ` + checkErrorQueryFrom(t, jsonDSL, "rq: filter: both field name and value in filter with subquery "+ + "are not empty (expecting exactly one of them)") + }) + + t.Run("dsl subquery can not be without 'select_filter'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_1", + "filters": [ + { + "field": "jid", + "cond": "EQ", + "value": [10] + } + ] + } + } + ] + } + ` + checkErrorQueryFrom(t, jsonDSL, "rq: subquery with Cond 'EQ' and without aggregations must have exactly 1 select_filter") + }) + + t.Run("dsl subquery can not be with empty 'select_filter'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "cond": "SET", + "subquery": { + "namespace": "test_namespace_dsl_joined_1", + "filters": [ + { + "field": "jid", + "cond": "EQ", + "value": [10] + } + ], + "select_filter": [] + } + } + ] + } + ` + checkErrorQueryFrom(t, jsonDSL, "rq: subquery with Cond 'SET' and without aggregations must have exactly 1 select_filter") + }) + + t.Run("dsl subquery can not have multiple 'select_filters'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_ft", + "filters": [ + { + "field": "id", + "cond": "EQ", + "value": [1] + } + ], + "select_filter": ["id", "description"] + } + } + ] + } + ` + checkErrorQueryFrom(t, jsonDSL, "rq: subquery can not have multiple select_filter's: [id description]") + }) + + t.Run("dsl subquery can not be with any/empty 'cond' and prohibited fields", func(t *testing.T) { + for _, cond := range []string{"any", "empty"} { + for _, field := range [][]string{{"limit", "1", "limit"}, {"offset", "1", "offset"}, + {"select_filter", `["jid"]`, "select filter"}, {"req_total", "true", "ReqTotal"}, + {"aggregations", `[{"fields": ["jid"], "type": "MAX"}]`, "aggregations"}} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "value": [], + "cond": "%s", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "EQ", + "value": [10] + } + ], + "select_filter": ["jid"], + "%s": %s + } + } + ] + } + ` + checkErrorQueryFrom(t, fmt.Sprintf(jsonDSL, cond, field[0], field[1]), + fmt.Sprintf("rq: filter: subquery with condition Any or Empty can not contain %s", field[2])) + } + } + }) + + t.Run("dsl subquery can not be with any/empty 'cond' and 'select_filter'", func(t *testing.T) { + for _, cond := range []string{"any", "empty"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "Value": [], + "cond": "%s", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "filters": [ + { + "field": "jid", + "cond": "EQ", + "value": [10] } ], - "on": [ + "select_filter": ["jid"] + } + } + ] + } + ` + checkErrorQueryFrom(t, fmt.Sprintf(jsonDSL, cond), + "rq: filter: subquery with condition Any or Empty can not contain select filter") + } + }) + + t.Run("dsl subquery can not be with any/empty 'cond' and 'field'", func(t *testing.T) { + for _, cond := range []string{"any", "empty"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "cond": "%s", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "filters": [ { - "left_field": "id", - "right_field": "jid", - "cond": "EQ" + "field": "jid", + "cond": "EQ", + "value": [10] } ] } @@ -1627,37 +2737,55 @@ func TestDSLQueries(t *testing.T) { ] } ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, value)), &dslQ) - require.EqualError(t, err, "range argument array must has 2 elements") + checkErrorQueryFrom(t, fmt.Sprintf(jsonDSL, cond), + "rq: filter: subquery with condition Any or Empty can not have Field in the filter") } }) - t.Run("dsl join invalid filter cond type", func(t *testing.T) { - for _, cond := range []string{"equal", "not", "1"} { + t.Run("dsl subquery can not be with eq/set 'cond' and empty 'value'", func(t *testing.T) { + for _, cond := range []string{"eq", "set"} { const jsonDSL = ` { "namespace": "test_namespace_dsl", "filters": [ { - "op": "AND", - "join_query": { - "type": "inner", + "value": [], + "cond": "%s", + "subquery": { "namespace": "test_namespace_dsl_joined_2", "filters": [ { - "op": "AND", - "field": "jid", - "cond": "%s", - "value": 1 + "field": "jid", + "cond": "EQ", + "value": [10] } ], - "on": [ + "select_filter": ["jid"] + } + } + ] + } + ` + checkErrorQueryFrom(t, fmt.Sprintf(jsonDSL, cond), + fmt.Sprintf("rq: filter: subquery with condition %s can not have nil target Value and empty field name", cond)) + } + }) + + t.Run("dsl subquery can not be with unsupported aggregations", func(t *testing.T) { + for _, agg := range []string{"distinct", "facet"} { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "aggregations": [ { - "left_field": "id", - "right_field": "jid", - "cond": "EQ" + "type": "%s", + "fields": ["jid"] } ] } @@ -1665,86 +2793,78 @@ func TestDSLQueries(t *testing.T) { ] } ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond)), &dslQ) - require.EqualError(t, err, fmt.Sprintf("cond type '%s' not found", cond)) + checkErrorQueryFrom(t, fmt.Sprintf(jsonDSL, agg), + fmt.Sprintf("rq: filter: unsupported aggregation for subquery: '%s'", agg)) } }) - t.Run("dsl join filter value array must be homogeneous", func(t *testing.T) { - for _, cond := range []string{"eq", "set"} { - for _, value := range [][]string{ - {"true, \"abc\"", "bool"}, {"false, 2", "bool"}, - {"1, \"2\"", "int/float"}, {"1.5, false", "int/float"}, - {"\"abc\", {}", "string"}, {"\"1\", 2", "string"}, {"\"a\", [\"b\"]", "string"}, - } { - const jsonDSL = ` + t.Run("dsl subquery can not be with both 'aggregations' and 'select_filter'", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ { - "namespace": "test_namespace_dsl", - "filters": [ - { - "op": "AND", - "join_query": { - "type": "inner", - "namespace": "test_namespace_dsl_joined_2", - "filters": [ - { - "op": "AND", - "field": "jid", - "cond": "%s", - "value": [%s] - } - ], - "on": [ - { - "left_field": "id", - "right_field": "jid", - "cond": "EQ" - } - ] + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "select_filter": ["jid"], + "aggregations": [ + { + "type": "max", + "fields": ["jid"] } - } - ] + ] + } } - ` + ] + } + ` + checkErrorQueryFrom(t, jsonDSL, + "rq: subquery can not have select_filter and aggregations at the same time") + }) - var dslQ dsl.DSL - err := json.Unmarshal([]byte(fmt.Sprintf(jsonDSL, cond, value[0])), &dslQ) - require.EqualError(t, err, fmt.Sprintf("array must be homogeneous (%s)", value[1])) - } + t.Run("dsl subquery can not contain more than 1 aggregation", func(t *testing.T) { + const jsonDSL = ` + { + "namespace": "test_namespace_dsl", + "filters": [ + { + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_2", + "select_filter": ["jid"], + "req_total": true, + "aggregations": [ + { + "type": "max", + "fields": ["jid"] + } + ] + } + } + ] } + ` + checkErrorQueryFrom(t, jsonDSL, + "rq: filter: subquery can not contain more than 1 aggregation / count request") }) - t.Run("dsl join with repeated fields: the next field overrides the previous one", func(t *testing.T) { + t.Run("dsl filters can not contain 'field' and 'join_query' at the same time", func(t *testing.T) { const jsonDSL = ` { - "namespace": "test_namespace_dsl_joined_1", "namespace": "test_namespace_dsl", - "sort": { - "field": "none", - "field": "id" - }, "filters": [ { - "op": "AND", + "field": "id", + "cond": "EQ", "join_query": { - "type": "left", "type": "inner", "namespace": "test_namespace_dsl_joined_2", - "filters": [ - { - "field": "jid", - "cond": "range", - "cond": "eq", - "value": 14, - "value": [15,16,17] - } - ], "on": [ { "left_field": "id", - "right_field": "id", "right_field": "jid", "cond": "EQ" } @@ -1754,191 +2874,96 @@ func TestDSLQueries(t *testing.T) { ] } ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{15, 16, 17} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + checkErrorQueryFrom(t, jsonDSL, + "rq: dsl filter can not contain both 'field' and 'join_query' at the same time") }) - t.Run("dsl unsupported fields don't affect the result", func(t *testing.T) { + t.Run("dsl filters can not contain 'filters' and 'join_query' at the same time", func(t *testing.T) { const jsonDSL = ` { "namespace": "test_namespace_dsl", - "sort": { - "field": "id" - }, "filters": [ - { - "field": "id", - "cond": "set", - "value": [1,9,15,11,14], - "some_unsupported_0": true - }, { "join_query": { "type": "inner", "namespace": "test_namespace_dsl_joined_2", - "filters": [ - { - "field": "jid", - "cond": "range", - "value": [11,15] - } - ], "on": [ { "left_field": "id", "right_field": "jid", "cond": "EQ" } - ], - "some_unsupported_1": "abc" - } - } - ], - "merge_queries": [ - { - "namespace": "test_namespace_dsl_joined_2", - "type": "select", + ] + }, "filters": [ { - "op": "And", - "field": "id", - "cond": "eq", - "value": [18] + "field": "jid", + "cond": "EQ", + "value": [10] } ] } - ], - "type": "select", - "select_functions": [ - "id = highlight(<,>)" - ], - "select_filter": ["age"], - "strict_mode": "rrr", - "some_unsupported_2": 123 + ] } ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{11, 14, 15} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + checkErrorQueryFrom(t, jsonDSL, + "rq: dsl filter can not contain both 'filters' and 'join_query' at the same time") }) - t.Run("dsl forsed sort", func(t *testing.T) { + t.Run("dsl filters can not contain 'field' and 'filters' at the same time", func(t *testing.T) { const jsonDSL = ` { "namespace": "test_namespace_dsl", - "sort": { - "field": "id", - "values": [98, 99] - }, "filters": [ { "field": "id", - "cond": "ge", - "value": 95 + "cond": "EQ", + "filters": [ + { + "field": "jid", + "cond": "EQ", + "value": [10] + } + ] } ] } ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - items, err := q.MustExec().FetchAll() - require.NoError(t, err) - expectedIDs := []int{98, 99, 95, 96, 97} - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) - }) - - t.Run("cant dsl sort with expression", func(t *testing.T) { - const jsonDSL = ` - { - "namespace": "test_namespace_dsl", - "sort": { - "field": "id+2" - }, - "filters": [] - } - ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - _, err = q.Exec().FetchAll() - require.ErrorContains(t, err, "Current query strict mode allows sort by existing fields only. "+ - "There are no fields with name 'id+2' in namespace 'test_namespace_dsl'") + checkErrorQueryFrom(t, jsonDSL, + "rq: dsl filter can not contain both 'field' and 'filters' at the same time") }) - t.Run("dsl join with sort", func(t *testing.T) { + t.Run("dsl subquery filters can not contain join_query", func(t *testing.T) { const jsonDSL = ` { "namespace": "test_namespace_dsl", - "sort": { - "field": "test_namespace_dsl_joined_2.jid", - "desc": false - }, - "explain": true, "filters": [ { - "join_query": { - "type": "inner", - "namespace": "test_namespace_dsl_joined_2", + "field": "id", + "cond": "EQ", + "subquery": { + "namespace": "test_namespace_dsl_joined_1", "filters": [ { - "field": "jid", - "cond": "set", - "value": [11, 19, 13, 14, 10] + "join_query": { + "type": "inner", + "namespace": "test_namespace_dsl_joined_2", + "on": [ + { + "left_field": "jid", + "right_field": "jid", + "cond": "EQ" + } + ] + } } ], - "on": [ - { - "left_field": "id", - "right_field": "jid", - "cond": "EQ" - } - ] + "select_filter": ["jid"] } } ] } ` - - var dslQ dsl.DSL - err := json.Unmarshal([]byte(jsonDSL), &dslQ) - require.NoError(t, err) - q, err := DBD.QueryFrom(dslQ) - require.NoError(t, err) - require.NotNil(t, q) - it := q.MustExec() - require.NoError(t, it.Error()) - explain, err := it.GetExplainResults() - assert.NoError(t, err) - assert.NotNil(t, explain) - expectedIDs := []int{10, 11, 13, 14, 19} - items, err := it.FetchAll() - require.NoError(t, err) - require.Equal(t, expectedIDs, getTesDSLJoinItemsIDs(items)) + checkErrorQueryFrom(t, jsonDSL, "rq: nested join quieries are not supported") }) } diff --git a/test/encdec_test.go b/test/encdec_test.go index 742ecbc08..628afa0f3 100644 --- a/test/encdec_test.go +++ b/test/encdec_test.go @@ -2,7 +2,9 @@ package reindexer import ( "encoding/json" + "fmt" "math/rand" + "reflect" "testing" "time" @@ -115,6 +117,34 @@ type HeterogeneousArrayItem struct { Interface interface{} } +type SingleElemSliceItem struct { + ID int `json:"id" reindex:"id,,pk"` + IdxStrSlice []string `json:"idx_str_slice" reindex:"idx_str_slice"` + IdxIntSlice []int64 `json:"idx_int_slice" reindex:"idx_int_slice"` + IdxFloatSlice []float64 `json:"idx_float_slice" reindex:"idx_float_slice"` + IdxBoolSlice []bool `json:"idx_bool_slice" reindex:"idx_bool_slice"` + NonIdxStrSlice []string `json:"non_idx_str_slice"` + NonIdxIntSlice []int64 `json:"non_idx_int_slice"` + NonIdxFloatSlice []float64 `json:"non_idx_float_slice"` + NonIdxBoolSlice []bool `json:"non_idx_bool_slice"` +} + +type SlicesConcatenationItem struct { + ID int `json:"id" reindex:"id,,pk"` + IdxStrSlice []string `json:"idx_str_slice" reindex:"idx_str_slice"` + IdxInt64Slice []int64 `json:"idx_int64_slice" reindex:"idx_int64_slice"` + IdxInt32Slice []int32 `json:"idx_int32_slice" reindex:"idx_int32_slice"` + IdxInt16Slice []int16 `json:"idx_int16_slice" reindex:"idx_int16_slice"` + IdxInt8Slice []int8 `json:"idx_int8_slice" reindex:"idx_int8_slice"` + IdxFloat64Slice []float64 `json:"idx_float64_slice" reindex:"idx_float64_slice"` + IdxBoolSlice []bool `json:"idx_bool_slice" reindex:"idx_bool_slice,-"` + NonIdxStrSlice []string `json:"non_idx_str_slice"` + NonIdxIntSlice []int `json:"non_idx_int_slice"` + NonIdxFloat32Slice []float32 `json:"non_idx_float32_slice"` + NonIdxBoolSlice []bool `json:"non_idx_bool_slice"` + NonIdxIfaceSlice []interface{} `json:"non_idx_iface_slice"` +} + func FillHeteregeneousArrayItem() { item := &HeterogeneousArrayItem{ ID: 1, @@ -131,6 +161,8 @@ func FillHeteregeneousArrayItem() { func init() { tnamespaces["test_items_encdec"] = TestItemEncDec{} tnamespaces["test_array_encdec"] = HeterogeneousArrayItem{} + tnamespaces["test_single_elem_slice"] = SingleElemSliceItem{} + tnamespaces["test_slices_concatenation"] = SlicesConcatenationItem{} } func FillTestItemsEncDec(start int, count int, pkgsCount int, asJson bool) { @@ -296,3 +328,148 @@ func TestEncDec(t *testing.T) { } q.Verify(t, iitems, []reindexer.AggregationResult{}, true) } + +func TestSingleElemToSlice(t *testing.T) { + ns := "test_single_elem_slice" + item := SingleElemSliceItem{ + ID: 1, + IdxStrSlice: []string{"str1"}, + IdxIntSlice: []int64{999}, + IdxFloatSlice: []float64{10.0}, + IdxBoolSlice: []bool{true}, + NonIdxStrSlice: []string{"str2"}, + NonIdxIntSlice: []int64{888}, + NonIdxFloatSlice: []float64{20.0}, + NonIdxBoolSlice: []bool{false}, + } + err := DB.Upsert(ns, + []byte(fmt.Sprintf(`{"id":%v, "idx_str_slice":"%v", "idx_int_slice":%v,"idx_float_slice":%v,"idx_bool_slice":%v, + "non_idx_str_slice":"%v","non_idx_int_slice":%v,"non_idx_float_slice":%v,"non_idx_bool_slice":%v}`, + item.ID, item.IdxStrSlice[0], item.IdxIntSlice[0], item.IdxFloatSlice[0], item.IdxBoolSlice[0], + item.NonIdxStrSlice[0], item.NonIdxIntSlice[0], item.NonIdxFloatSlice[0], item.NonIdxBoolSlice[0])), + ) + require.NoError(t, err) + + resItems, err := newTestQuery(DB, ns).MustExec(t).FetchAll() + require.NoError(t, err) + require.Equal(t, len(resItems), 1) + resItem, ok := resItems[0].(*SingleElemSliceItem) + require.True(t, ok) + require.Equal(t, *resItem, item) +} + +func TestSlicesConcatenation(t *testing.T) { + ns := "test_slices_concatenation" + item := SlicesConcatenationItem{ + ID: 1, + IdxStrSlice: []string{"str10", "str11", "str12", "str13"}, + IdxInt64Slice: []int64{110, 120, 130, 140, 150, 160}, + IdxInt32Slice: []int32{310, 320, 330, 340, 350, 360}, + IdxInt16Slice: []int16{210, 420, 430, 440, 450, 460}, + IdxInt8Slice: []int8{10, 20, 30, 40, 50, 60}, + IdxFloat64Slice: []float64{120.0, 140.5, 160.0, 170.5, 180.92}, + IdxBoolSlice: []bool{true, true, false, true}, + NonIdxStrSlice: []string{"str20", "str21", "str22", "str23"}, + NonIdxIntSlice: []int{10, 20, 30, 40, 50, 60}, + NonIdxFloat32Slice: []float32{20.0, 40.5, 60.0, 70.5, 80.92}, + NonIdxBoolSlice: []bool{false, false, true, false}, + NonIdxIfaceSlice: []interface{}{"istr1", "istr2", 11, 22.4, true, false}, + } + appendInterface := func(slice []interface{}, a interface{}) []interface{} { + ra := reflect.ValueOf(a) + if ra.Kind() == reflect.Slice { + for i := 0; i < ra.Len(); i++ { + slice = append(slice, ra.Index(i).Interface()) + } + return slice + } + return append(slice, a) + } + sl := make([]interface{}, 0) + rv := reflect.ValueOf(item) + for i := 0; i < rv.NumField(); i++ { + field := rv.Field(i).Interface() + sl = appendInterface(sl, field) + } + + t.Run("slices concatenation variant 1", func(t *testing.T) { + err := DB.Upsert(ns, + []byte(fmt.Sprintf(`{"id":%v, + "idx_str_slice":"%v", "idx_str_slice":["%v","%v"], "idx_str_slice":"%v", + "idx_int64_slice":%v, "idx_int64_slice":[%v,%v,%v], "idx_int64_slice":[%v], "idx_int64_slice":%v, + "idx_int32_slice":%v, "idx_int32_slice":[%v,%v,%v], "idx_int32_slice":[%v], "idx_int32_slice":%v, + "idx_int16_slice":%v, "idx_int16_slice":[%v,%v,%v], "idx_int16_slice":[%v], "idx_int16_slice":%v, + "idx_int8_slice":%v, "idx_int8_slice":[%v,%v,%v], "idx_int8_slice":[%v], "idx_int8_slice":%v, + "idx_float64_slice":%v, "idx_float64_slice":[%v,%v,%v], "idx_float64_slice":%v, + "idx_bool_slice":%v, "idx_bool_slice":[%v,%v], "idx_bool_slice":%v, + "non_idx_str_slice":"%v", "non_idx_str_slice":["%v","%v"], "non_idx_str_slice":"%v", + "non_idx_int_slice":%v, "non_idx_int_slice":[%v,%v,%v], "non_idx_int_slice":[%v], "non_idx_int_slice":%v, + "non_idx_float32_slice":%v, "non_idx_float32_slice":[%v,%v,%v], "non_idx_float32_slice":%v, + "non_idx_bool_slice":%v, "non_idx_bool_slice":[%v,%v], "non_idx_bool_slice":%v, + "non_idx_iface_slice":"%v", "non_idx_iface_slice":"%v", "non_idx_iface_slice":%v, "non_idx_iface_slice":%v, "non_idx_iface_slice":%v, "non_idx_iface_slice":%v}`, + sl...)), + ) + require.NoError(t, err) + + resItems, err := newTestQuery(DB, ns).MustExec(t).FetchAll() + require.NoError(t, err) + require.Equal(t, len(resItems), 1) + resItem, ok := resItems[0].(*SlicesConcatenationItem) + require.True(t, ok) + require.Equal(t, *resItem, item) + }) + + t.Run("slices concatenation variant 2", func(t *testing.T) { + err := DB.Upsert(ns, + []byte(fmt.Sprintf(`{"id":%v, + "idx_str_slice":["%v","%v"], "idx_str_slice":"%v", "idx_str_slice":"%v", + "idx_int64_slice":[%v,%v,%v], "idx_int64_slice":%v, "idx_int64_slice":[%v], "idx_int64_slice":%v, + "idx_int32_slice":[%v,%v,%v], "idx_int32_slice":%v, "idx_int32_slice":[%v], "idx_int32_slice":%v, + "idx_int16_slice":[%v,%v,%v], "idx_int16_slice":%v, "idx_int16_slice":[%v], "idx_int16_slice":%v, + "idx_int8_slice":[%v,%v,%v], "idx_int8_slice":%v, "idx_int8_slice":[%v], "idx_int8_slice":%v, + "idx_float64_slice":[%v,%v,%v], "idx_float64_slice":%v, "idx_float64_slice":%v, + "idx_bool_slice":[%v,%v], "idx_bool_slice":%v, "idx_bool_slice":%v, + "non_idx_str_slice":["%v","%v"], "non_idx_str_slice":"%v", "non_idx_str_slice":"%v", + "non_idx_int_slice":[%v,%v,%v], "non_idx_int_slice":%v, "non_idx_int_slice":[%v], "non_idx_int_slice":%v, + "non_idx_float32_slice":[%v,%v,%v], "non_idx_float32_slice":%v, "non_idx_float32_slice":%v, + "non_idx_bool_slice":[%v,%v], "non_idx_bool_slice":%v, "non_idx_bool_slice":%v, + "non_idx_iface_slice":["%v","%v"], "non_idx_iface_slice":%v, "non_idx_iface_slice":%v, "non_idx_iface_slice":[%v,%v]}`, + sl...)), + ) + require.NoError(t, err) + + resItems, err := newTestQuery(DB, ns).MustExec(t).FetchAll() + require.NoError(t, err) + require.Equal(t, len(resItems), 1) + resItem, ok := resItems[0].(*SlicesConcatenationItem) + require.True(t, ok) + require.Equal(t, *resItem, item) + }) + + t.Run("slices concatenation variant 3", func(t *testing.T) { + err := DB.Upsert(ns, + []byte(fmt.Sprintf(`{"id":%v, + "idx_str_slice":["%v","%v"], "idx_str_slice":["%v","%v"], + "idx_int64_slice":[%v,%v,%v], "idx_int64_slice":[%v,%v,%v], + "idx_int32_slice":[%v,%v,%v], "idx_int32_slice":[%v,%v,%v], + "idx_int16_slice":[%v,%v,%v], "idx_int16_slice":[%v,%v,%v], + "idx_int8_slice":[%v,%v,%v], "idx_int8_slice":[%v,%v,%v], + "idx_float64_slice":[%v,%v,%v], "idx_float64_slice":[%v,%v], + "idx_bool_slice":[%v,%v], "idx_bool_slice":[%v,%v], + "non_idx_str_slice":["%v","%v"], "non_idx_str_slice":["%v","%v"], + "non_idx_int_slice":[%v,%v,%v], "non_idx_int_slice":[%v,%v,%v], + "non_idx_float32_slice":[%v,%v,%v], "non_idx_float32_slice":[%v,%v], + "non_idx_bool_slice":[%v,%v], "non_idx_bool_slice":[%v,%v], + "non_idx_iface_slice":["%v","%v"], "non_idx_iface_slice":[%v,%v], "non_idx_iface_slice":[%v,%v]}`, + sl...)), + ) + require.NoError(t, err) + + resItems, err := newTestQuery(DB, ns).MustExec(t).FetchAll() + require.NoError(t, err) + require.Equal(t, len(resItems), 1) + resItem, ok := resItems[0].(*SlicesConcatenationItem) + require.True(t, ok) + require.Equal(t, *resItem, item) + }) +} diff --git a/test/fields_autogen_test.go b/test/fields_autogen_test.go index 0813cb0af..2f25b6176 100644 --- a/test/fields_autogen_test.go +++ b/test/fields_autogen_test.go @@ -26,6 +26,9 @@ func init() { } func TestAutogen(t *testing.T) { + + currentSerial := 0 + t.Run("field should be updated with current timestamp using NOW() function", func(t *testing.T) { precepts := []string{"updated_time=NOW()"} item := TestItemAutogen{} @@ -51,9 +54,10 @@ func TestAutogen(t *testing.T) { item := TestItemAutogen{} err := DB.Upsert(ns, &item, precepts...) require.NoError(t, err) + currentSerial += 1 - assert.Equal(t, 1, item.Age) - assert.Equal(t, int64(1), item.Genre) + assert.Equal(t, currentSerial, item.Age) + assert.Equal(t, int64(currentSerial), item.Genre) t.Run("serial field should be increased by 5 after 5 iterations (must be equal 6 after previous test)", func(t *testing.T) { precepts := []string{"genre=SERIAL()", "age=serial()"} @@ -61,70 +65,84 @@ func TestAutogen(t *testing.T) { for i := 0; i < 5; i++ { err := DB.Upsert(ns, &item, precepts...) require.NoError(t, err) + currentSerial += 1 } - assert.Equal(t, 6, item.Age) - assert.Equal(t, int64(6), item.Genre) + assert.Equal(t, currentSerial, item.Age) + assert.Equal(t, int64(currentSerial), item.Genre) }) }) t.Run("fill on insert, update, upsert", func(t *testing.T) { - precepts := []string{"updated_time=NOW()"} + precepts := []string{"updated_time=NOW()", "age=SERIAL()"} item := TestItemAutogen{ID: rand.Intn(100000000)} _, err := DB.Insert(ns, &item, precepts...) require.NoError(t, err) + currentSerial += 1 assert.GreaterOrEqual(t, item.UpdatedTime, time.Now().Unix()-1) assert.LessOrEqual(t, item.UpdatedTime, time.Now().Unix()) + assert.Equal(t, currentSerial, item.Age) item = TestItemAutogen{} err = DB.Upsert(ns, &item, precepts...) require.NoError(t, err) + currentSerial += 1 assert.GreaterOrEqual(t, item.UpdatedTime, time.Now().Unix()-1) assert.LessOrEqual(t, item.UpdatedTime, time.Now().Unix()) + assert.Equal(t, currentSerial, item.Age) item = TestItemAutogen{} _, err = DB.Update(ns, &item, precepts...) require.NoError(t, err) + currentSerial += 1 assert.GreaterOrEqual(t, item.UpdatedTime, time.Now().Unix()-1) assert.LessOrEqual(t, item.UpdatedTime, time.Now().Unix()) + assert.Equal(t, currentSerial, item.Age) }) - t.Run("fill on upsert not exist item", func(t *testing.T) { - precepts := []string{"updated_time=NOW()"} + t.Run("fill on upsert nonexist item", func(t *testing.T) { + precepts := []string{"updated_time=NOW()", "age=SERIAL()"} item := TestItemAutogen{ID: rand.Intn(100000000)} err := DB.Upsert(ns, &item, precepts...) require.NoError(t, err) + currentSerial += 1 assert.GreaterOrEqual(t, item.UpdatedTime, time.Now().Unix()-1) assert.LessOrEqual(t, item.UpdatedTime, time.Now().Unix()) + assert.Equal(t, currentSerial, item.Age) }) - t.Run("not fill on update not exist item", func(t *testing.T) { - precepts := []string{"updated_time=NOW()"} + t.Run("doesn't fill on update nonexist item", func(t *testing.T) { + precepts := []string{"updated_time=NOW()", "age=SERIAL()"} item := TestItemAutogen{ID: rand.Intn(100000000)} count, err := DB.Update(ns, &item, precepts...) require.NoError(t, err) + currentSerial += 1 // remove after 1602 assert.Equal(t, 0, count) assert.Equal(t, int64(0), item.UpdatedTime) + assert.Equal(t, 0, item.Age) }) - t.Run("not fill on insert exist item", func(t *testing.T) { - precepts := []string{"updated_time=NOW()"} + t.Run("doesn't fill on insert exist item", func(t *testing.T) { + precepts := []string{"updated_time=NOW()", "age=SERIAL()"} id := rand.Intn(100000000) item := TestItemAutogen{ID: id} count, err := DB.Insert(ns, &item, precepts...) require.NoError(t, err) + currentSerial += 1 assert.Equal(t, 1, count) assert.GreaterOrEqual(t, item.UpdatedTime, time.Now().Unix()-1) assert.LessOrEqual(t, item.UpdatedTime, time.Now().Unix()) + assert.Equal(t, currentSerial, item.Age) item = TestItemAutogen{ID: id} count, err = DB.Insert(ns, &item, precepts...) require.NoError(t, err) assert.Equal(t, 0, count) assert.Equal(t, int64(0), item.UpdatedTime) + assert.Equal(t, 0, item.Age) }) } diff --git a/test/join_test.go b/test/join_test.go index 6b6f42695..46687225c 100644 --- a/test/join_test.go +++ b/test/join_test.go @@ -6,8 +6,10 @@ import ( "sort" "strings" "testing" + "time" "github.com/restream/reindexer/v3" + "github.com/restream/reindexer/v3/bindings/builtinserver/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -745,3 +747,92 @@ func TestExplainJoin(t *testing.T) { }, }) } + +type strictJoinHandlerNs struct { + Id int `reindex:"id,,pk"` + Data int `reindex:"data"` + JoinedData []*strictJoinHandlerNs `reindex:"joined_data,,joined"` +} + +func initNsForStrictJoinHandlers(t *testing.T, db *reindexer.Reindexer, ns string, count int) { + db.DropNamespace(ns) + err := db.OpenNamespace(ns, reindexer.DefaultNamespaceOptions().NoStorage(), strictJoinHandlerNs{}) + assert.NoError(t, err) + tx := db.MustBeginTx(ns) + for i := 0; i < count; i++ { + err = tx.Upsert(strictJoinHandlerNs{i, i, nil}) + assert.NoError(t, err) + } + tx.MustCommit() +} + +func TestStrictJoinHandlers(t *testing.T) { + if len(DB.slaveList) > 0 { + t.Skip() + } + t.Parallel() + + nsMain := "strict_join_handlers_main" + nsJoined := "strict_join_handlers_joined" + + cfg := config.DefaultServerConfig() + cfg.Net.HTTPAddr = "0:17173" + cfg.Net.RPCAddr = "0:17174" + cfg.Storage.Path = "" + + db := reindexer.NewReindex("builtinserver://xxx", reindexer.WithServerConfig(time.Second*100, cfg), reindexer.WithStrictJoinHandlers()) + defer db.Close() + assert.NoError(t, db.Status().Err) + + initNsForStrictJoinHandlers(t, db, nsMain, 5) + initNsForStrictJoinHandlers(t, db, nsJoined, 20) + + t.Run("expecting error without join handler", func(t *testing.T) { + qjoin := db.Query(nsJoined).Where("data", reindexer.GT, 0) + _, err := db.Query(nsMain). + InnerJoin(qjoin, "joined_data"). + On("id", reindexer.EQ, "id"). + Exec().FetchAll() + require.ErrorContains(t, err, "join handler is missing.") + }) + + t.Run("expecting error with join handler returning 'true'", func(t *testing.T) { + mainQ := db.Query(nsMain) + qjoin := db.Query(nsJoined).Where("data", reindexer.GT, 0) + mainQ.InnerJoin(qjoin, "joined_data").On("id", reindexer.EQ, "id") + _, err := mainQ. + JoinHandler("joined_data", func(field string, item interface{}, subitems []interface{}) bool { return true }). + Exec().FetchAll() + require.ErrorContains(t, err, "join handler was found, but returned 'true' and the field was handled via reflection.") + }) + + t.Run("expecting success with join handler returning 'false'", func(t *testing.T) { + mainQ := db.Query(nsMain) + qjoin := db.Query(nsJoined).Where("data", reindexer.GT, 0) + mainQ.InnerJoin(qjoin, "joined_data").On("id", reindexer.EQ, "id") + _, err := mainQ. + JoinHandler("joined_data", func(field string, item interface{}, subitems []interface{}) bool { return false }). + Exec().FetchAll() + require.NoError(t, err) + }) + + t.Run("expecting success with join handler returning 'false' set via joined query", func(t *testing.T) { + qjoin := db.Query(nsJoined).Where("data", reindexer.GT, 0) + _, err := db.Query(nsMain). + InnerJoin(qjoin, "joined_data"). + On("id", reindexer.EQ, "id"). + JoinHandler("joined_data", func(field string, item interface{}, subitems []interface{}) bool { return false }). + Exec().FetchAll() + require.NoError(t, err) + }) + + t.Run("expecting error with join handler set before the actual join", func(t *testing.T) { + qjoin := db.Query(nsJoined).Where("data", reindexer.GT, 0) + _, err := db.Query(nsMain). + JoinHandler("joined_data", func(field string, item interface{}, subitems []interface{}) bool { return false }). + InnerJoin(qjoin, "joined_data"). + On("id", reindexer.EQ, "id"). + Exec().FetchAll() + require.ErrorContains(t, err, "join handler is missing.") + }) +} diff --git a/test/queries_test.go b/test/queries_test.go index 440217696..eae306113 100644 --- a/test/queries_test.go +++ b/test/queries_test.go @@ -589,9 +589,12 @@ func TestSTDistanceWrappers(t *testing.T) { searchPoint := randPoint() distance := randFloat(0, 2) sortPoint := randPoint() - it1, err := DBD.Query(ns).DWithin(field1, searchPoint, distance).SortStPointDistance(field1, sortPoint, false).ExecToJson().FetchAll() + it1, err := DBD.Query(ns).DWithin(field1, searchPoint, distance).SortStPointDistance(field1, sortPoint, false). + ExecToJson().FetchAll() require.NoError(t, err) - it2, err := DBD.Query(ns).DWithin(field1, searchPoint, distance).Sort(fmt.Sprintf("ST_Distance(%s, ST_GeomFromText('point(%f %f)'))", field1, sortPoint[0], sortPoint[1]), false).ExecToJson().FetchAll() + it2, err := DBD.Query(ns).DWithin(field1, searchPoint, distance).Sort(fmt.Sprintf("ST_Distance(%s, ST_GeomFromText('point(%s %s)'))", + field1, strconv.FormatFloat(sortPoint[0], 'f', -1, 64), strconv.FormatFloat(sortPoint[1], 'f', -1, 64)), false). + ExecToJson().FetchAll() require.NoError(t, err) require.Equal(t, string(it1), string(it2)) } @@ -1114,6 +1117,27 @@ func callQueriesSequence(t *testing.T, namespace string, distinct []string, sort Not().Where("uuid_array", reindexer.SET, randUuidArray(rand.Int()%10)). ExecAndVerify(t) + newTestQuery(DB, namespace).Distinct(distinct).Sort(sort, desc).ReqTotal(). + WhereQuery(t, newTestQuery(DB, namespace).Where("id", reindexer.EQ, mkID(rand.Int()%5000)), + reindexer.ANY, nil). + ExecAndVerify(t) + + newTestQuery(DB, namespace).Distinct(distinct).Sort(sort, desc).ReqTotal(). + WhereQuery(t, newTestQuery(DB, namespace).Select("id").Where("id", reindexer.GT, mkID(rand.Int()%5000)).Limit(10), reindexer.LT, mkID(rand.Int()%5000)). + ExecAndVerify(t) + + newTestQuery(DB, namespace).Distinct(distinct).Sort(sort, desc).ReqTotal(). + WhereQuery(t, newTestQuery(DB, namespace).Where("id", reindexer.GT, mkID(rand.Int()%5000)).AggregateAvg("id"), reindexer.LT, mkID(rand.Int()%5000)). + ExecAndVerify(t) + + newTestQuery(DB, namespace).Distinct(distinct).Sort(sort, desc).ReqTotal(). + Where("id", reindexer.SET, newTestQuery(DB, namespace).Select("id").Where("id", reindexer.GT, mkID(rand.Int()%5000)).Limit(10)). + ExecAndVerify(t) + + newTestQuery(DB, namespace).Distinct(distinct).Sort(sort, desc).ReqTotal(). + Where("id", reindexer.LE, newTestQuery(DB, namespace).AggregateAvg("id").Where("id", reindexer.LT, mkID(rand.Int()%5000+5))). + ExecAndVerify(t) + if !testComposite { return } @@ -1979,6 +2003,7 @@ func TestQrIdleTimeout(t *testing.T) { t.Run("check if qr wil be correctly reused after connections drop", func(t *testing.T) { db := reindexer.NewReindex(*dsn, reindexer.WithConnPoolSize(1), reindexer.WithDedicatedServerThreads()) + db.SetLogger(testLogger) err := db.RegisterNamespace(namespace, reindexer.DefaultNamespaceOptions(), TestItemSimple{}) require.NoError(t, err) const qrCount = 32 @@ -2017,6 +2042,7 @@ func TestQrIdleTimeout(t *testing.T) { t.Run("concurrent query results timeouts", func(t *testing.T) { db := reindexer.NewReindex(*dsn, reindexer.WithConnPoolSize(16), reindexer.WithDedicatedServerThreads()) defer db.Close() + db.SetLogger(testLogger) err := db.RegisterNamespace(namespace, reindexer.DefaultNamespaceOptions(), TestItemSimple{}) require.NoError(t, err) const fillingRoutines = 5 @@ -2078,6 +2104,9 @@ func TestQrIdleTimeout(t *testing.T) { _, err = qrs[qrCount].FetchAll() assert.NoError(t, err) + if testLogger != nil { + testLogger.Printf(reindexer.ERROR, "----- Expecting a lot of query results timeout errors after this line -----") + } for i := 1; i < qrCount; i++ { _, err = qrs[i].FetchAll() assert.Error(t, err, "i = %d", i) @@ -2085,11 +2114,15 @@ func TestQrIdleTimeout(t *testing.T) { atomic.AddInt32(&stop, 1) wg.Wait() + if testLogger != nil { + testLogger.Printf(reindexer.ERROR, "----- No more query results timeout errors after this line -----") + } }) t.Run("check if timed out query results will be reused after client's qr buffer overflow", func(t *testing.T) { db := reindexer.NewReindex(*dsn, reindexer.WithConnPoolSize(1), reindexer.WithDedicatedServerThreads()) defer db.Close() + db.SetLogger(testLogger) err := db.RegisterNamespace(namespace, reindexer.DefaultNamespaceOptions(), TestItemSimple{}) require.NoError(t, err) const qrCount = 256 @@ -2110,6 +2143,10 @@ func TestQrIdleTimeout(t *testing.T) { qrs = append(qrs, it) } + if testLogger != nil { + testLogger.Printf(reindexer.ERROR, "----- Expecting connection drop and a lot of query results EOF errors after this line -----") + } + // Actual overflow. Connect must be dropped it := db.Query(namespace).FetchCount(fetchCount).Limit(fetchCount * 2).Exec() assert.Error(t, it.Error()) @@ -2120,6 +2157,10 @@ func TestQrIdleTimeout(t *testing.T) { assert.Error(t, err, "i = %d", i) } + if testLogger != nil { + testLogger.Printf(reindexer.ERROR, "----- No more query results EOF errors after this line -----") + } + // Trying to create new QRs after connection drop for i := 0; i < qrCount; i++ { it := db.Query(namespace).FetchCount(fetchCount).Limit(fetchCount * 2).Exec() diff --git a/test/query_test.go b/test/query_test.go index 924523459..bdbdba7be 100644 --- a/test/query_test.go +++ b/test/query_test.go @@ -47,8 +47,26 @@ const ( oneFieldEntry = iota twoFieldsEntry bracket + alwaysTrue + alwaysFalse ) +const ( + aggSum = reindexer.AggSum + aggAvg = reindexer.AggAvg + aggMin = reindexer.AggMin + aggMax = reindexer.AggMax + aggFacet = reindexer.AggFacet +) + +var aggNames = map[int]string{ + aggSum: "SUM", + aggAvg: "AVG", + aggMin: "MIN", + aggMax: "MAX", + aggFacet: "FACET", +} + type queryTestEntryContainer struct { op int data interface{} @@ -76,6 +94,11 @@ type queryBetweenFieldsTestEntry struct { secondFieldIdx [][]int } +type aggTest struct { + fields []string + aggType int +} + // Test Query to DB object type queryTest struct { q *reindexer.Query @@ -97,7 +120,10 @@ type queryTest struct { deepReplEqual bool needVerify bool handClose bool + selectFilters []string + aggregations []aggTest } + type testNamespace struct { items map[string]interface{} pkIdx [][]int @@ -132,6 +158,8 @@ func newTestQuery(db *ReindexerWrapper, namespace string, needVerify ...bool) *q qt.limitItems = 0 qt.startOffset = 0 qt.reqTotalCount = false + qt.selectFilters = qt.selectFilters[:0] + qt.aggregations = qt.aggregations[:0] } qt.q = db.GetBaseQuery(namespace) qt.deepReplEqual = false @@ -275,6 +303,23 @@ func (tx *txTest) Query() *queryTest { } +func (entry *queryTestEntry) toString() (ret string) { + ret += entry.index + " " + queryNames[entry.condition] + " " + if len(entry.keys) > 1 { + ret += "(" + } + for i, c := range entry.keys { + if i != 0 { + ret += "," + } + ret += fmt.Sprintf("%v", c.Interface()) + } + if len(entry.keys) > 1 { + ret += ")" + } + return ret +} + func (qt *queryTestEntryTree) toString() (ret string) { if len(qt.data) < 1 { return ret @@ -298,29 +343,43 @@ func (qt *queryTestEntryTree) toString() (ret string) { case bracket: ret += "(" + d.data.(*queryTestEntryTree).toString() + ")" case oneFieldEntry: - entry := d.data.(*queryTestEntry) - ret += entry.index + " " + queryNames[entry.condition] + " " - if len(entry.keys) > 1 { - ret += "(" - } - for i, c := range entry.keys { - if i != 0 { - ret += "," - } - ret += fmt.Sprintf("%v", c.Interface()) - } - if len(entry.keys) > 1 { - ret += ")" - } + ret += d.data.(*queryTestEntry).toString() case twoFieldsEntry: entry := d.data.(*queryBetweenFieldsTestEntry) ret += entry.firstField + " " + queryNames[entry.condition] + " " + entry.secondField + case alwaysTrue, alwaysFalse: + ret += d.data.(string) } } return ret } func (qt *queryTest) toString() (ret string) { + for i, dIdx := range qt.distinctIndexes { + if i != 0 { + ret += ", " + } + ret += "DISTINCT(" + dIdx + ")" + } + for i, idx := range qt.selectFilters { + if i != 0 || len(qt.distinctIndexes) != 0 { + ret += ", " + } + ret += idx + } + for i, agg := range qt.aggregations { + if i != 0 || len(qt.distinctIndexes) != 0 || len(qt.selectFilters) != 0 { + ret += ", " + } + ret += aggNames[agg.aggType] + "(" + for j, f := range agg.fields { + if j != 0 { + ret += ", " + } + ret += f + } + ret += ")" + } ret += " FROM " + qt.q.Namespace if len(qt.entries.data) > 0 { ret += " WHERE " + qt.entries.toString() @@ -351,12 +410,6 @@ func (qt *queryTest) toString() (ret string) { if qt.startOffset != 0 { ret += " OFFSET " + strconv.Itoa(qt.startOffset) } - for i, dIdx := range qt.distinctIndexes { - if i != 0 { - ret += "," - } - ret += " DISTINCT(" + dIdx + ")" - } return ret } @@ -369,6 +422,22 @@ func (qt *queryTestEntryTree) addEntry(entry queryTestEntry, op int) { } } +func (qt *queryTestEntryTree) addAlwaysTrue(op int, s string) { + if qt.activeChild > 0 { + qt.data[qt.activeChild-1].data.(*queryTestEntryTree).addAlwaysTrue(op, s) + } else { + qt.data = append(qt.data, queryTestEntryContainer{op, s, alwaysTrue}) + } +} + +func (qt *queryTestEntryTree) addAlwaysFalse(op int, s string) { + if qt.activeChild > 0 { + qt.data[qt.activeChild-1].data.(*queryTestEntryTree).addAlwaysFalse(op, s) + } else { + qt.data = append(qt.data, queryTestEntryContainer{op, s, alwaysFalse}) + } +} + func (qt *queryTestEntryTree) addTwoFieldsEntry(entry queryBetweenFieldsTestEntry, op int) { if qt.activeChild > 0 { qt.data[qt.activeChild-1].data.(*queryTestEntryTree).addTwoFieldsEntry(entry, op) @@ -392,29 +461,83 @@ func (qt *queryTest) DeepReplEqual() *queryTest { return qt } -func (qt *queryTest) where(index string, condition int, keys interface{}) *queryTest { - qte := queryTestEntry{index: index, condition: condition, ikeys: keys} - +func keysFromInterface(keys interface{}) []reflect.Value { + res := []reflect.Value{} if keys != nil { if reflect.TypeOf(keys).Kind() == reflect.Slice || reflect.TypeOf(keys).Kind() == reflect.Array { for i := 0; i < reflect.ValueOf(keys).Len(); i++ { - qte.keys = append(qte.keys, reflect.ValueOf(keys).Index(i)) + res = append(res, reflect.ValueOf(keys).Index(i)) } } else { - qte.keys = append(qte.keys, reflect.ValueOf(keys)) + res = append(res, reflect.ValueOf(keys)) } } + return res +} + +func (qt *queryTest) newQueryTestEntry(index string, condition int, keys interface{}) queryTestEntry { + qte := queryTestEntry{index: index, condition: condition, ikeys: keys} + + qte.keys = keysFromInterface(keys) qte.fieldIdx, _ = qt.ns.getField(index) + return qte +} + +func (qt *queryTest) where(index string, condition int, keys interface{}) *queryTest { + qte := qt.newQueryTestEntry(index, condition, keys) qt.entries.addEntry(qte, qt.nextOp) qt.nextOp = opAND return qt } +func (qt *queryTest) fieldSubQueryToString(index string, condition int, subQuery *queryTest) string { + qte := qt.newQueryTestEntry(index, condition, "(" + subQuery.toString() + ")") + return qte.toString() +} + +func (qt *queryTest) whereFieldQuery(index string, condition int, subQuery *queryTest) *queryTest { + it := subQuery.q.Exec() + defer it.Close() + if aggRes := it.AggResults(); len(aggRes) == 0 { + if len(subQuery.selectFilters) == 0 { + panic(fmt.Errorf("Broken subQuery")) + } + var vals []interface{} + fieldIdx, _ := qt.ns.getField(index) + for it.Next() { + vv := getValues(it.Object(), fieldIdx) + for _, v := range vv { + vals = append(vals, v.Interface()) + } + } + qt.where(index, condition, vals) + } else { + if aggRes[0].Value == nil { + qt.entries.addAlwaysFalse(qt.nextOp, qt.fieldSubQueryToString(index, condition, subQuery)) + qt.nextOp = opAND + } else { + qt.where(index, condition, *aggRes[0].Value) + } + } + return qt +} + // Where - Add where condition to DB query func (qt *queryTest) Where(index string, condition int, keys interface{}) *queryTest { - qt.q.Where(index, condition, keys) - return qt.where(index, condition, keys) + t := reflect.TypeOf(keys) + if t == reflect.TypeOf((*queryTest)(nil)).Elem() { + subQuery := keys.(queryTest) + qt.q.Where(index, condition, subQuery.q) + return qt.whereFieldQuery(index, condition, &subQuery) + } else if keys != nil && t.Kind() == reflect.Ptr && t.Elem() == reflect.TypeOf((*queryTest)(nil)).Elem() { + subQuery := keys.(*queryTest) + qt.q.Where(index, condition, subQuery.q) + return qt.whereFieldQuery(index, condition, subQuery) + } else { + qt.q.Where(index, condition, keys) + return qt.where(index, condition, keys) + } } // WhereUUID - Add where condition with UUID args. @@ -425,6 +548,48 @@ func (qt *queryTest) WhereUuid(index string, condition int, keys ...string) *que return qt.where(index, condition, keys) } +func (qt *queryTest) subQueryToString(subQuery *queryTest, condition int, keys interface{}) string { + qte := qt.newQueryTestEntry("(" + subQuery.toString() + ")", condition, keys) + return qte.toString() +} + +func (qt *queryTest) whereQuery(t *testing.T, subQuery *queryTest, condition int, keys interface{}) *queryTest { + if condition == reindexer.ANY || condition == reindexer.EMPTY { + subQuery.Limit(1) + } + it := subQuery.Exec(t) + defer it.Close() + res := false + if condition == reindexer.ANY || condition == reindexer.EMPTY { + res = (it.Count() != 0) == (condition == reindexer.ANY) + } else if aggRes := it.AggResults(); len(aggRes) == 0 { + require.NotEmpty(t, subQuery.selectFilters, "Broken subquery") + for it.Next() { + qte := qt.newQueryTestEntry(subQuery.selectFilters[0], condition, keys) + if checkCondition(t, subQuery.ns, &qte, it.Object()) { + res = true + break + } + } + } else { + if aggRes[0].Value != nil { + res = checkValue(t, reflect.ValueOf(*aggRes[0].Value), condition, keysFromInterface(keys)) + } + } + if res { + qt.entries.addAlwaysTrue(qt.nextOp, qt.subQueryToString(subQuery, condition, keys)) + } else { + qt.entries.addAlwaysFalse(qt.nextOp, qt.subQueryToString(subQuery, condition, keys)) + } + qt.nextOp = opAND + return qt +} + +func (qt *queryTest) WhereQuery(t *testing.T, subQuery *queryTest, condition int, keys interface{}) *queryTest { + qt.q.WhereQuery(subQuery.q, condition, keys) + return qt.whereQuery(t, subQuery, condition, keys) +} + func (qt *queryTest) WhereBetweenFields(firstField string, condition int, secondField string) *queryTest { qt.q.WhereBetweenFields(firstField, condition, secondField) qte := queryBetweenFieldsTestEntry{firstField: firstField, condition: condition, secondField: secondField} @@ -629,6 +794,7 @@ func (qt *queryTest) Explain() *queryTest { // SelectFilter func (qt *queryTest) Select(filters ...string) *queryTest { qt.q.Select(filters...) + qt.selectFilters = filters return qt } @@ -716,25 +882,33 @@ func (qt *queryTest) JoinHandler(field string, handler reindexer.JoinHandler) *q return qt } -func (qt *queryTest) AggregateSum(field string) { +func (qt *queryTest) AggregateSum(field string) *queryTest { qt.q.AggregateSum(field) + qt.aggregations = append(qt.aggregations, aggTest{[]string{field}, aggSum}) + return qt } -func (qt *queryTest) AggregateAvg(field string) { +func (qt *queryTest) AggregateAvg(field string) *queryTest { qt.q.AggregateAvg(field) + qt.aggregations = append(qt.aggregations, aggTest{[]string{field}, aggAvg}) + return qt } -func (qt *queryTest) AggregateMin(field string) { +func (qt *queryTest) AggregateMin(field string) *queryTest { qt.q.AggregateMin(field) + qt.aggregations = append(qt.aggregations, aggTest{[]string{field}, aggMin}) + return qt } -func (qt *queryTest) AggregateMax(field string) { +func (qt *queryTest) AggregateMax(field string) *queryTest { + qt.aggregations = append(qt.aggregations, aggTest{[]string{field}, aggMax}) qt.q.AggregateMax(field) + return qt } func (qt *queryTest) AggregateFacet(fields ...string) *reindexer.AggregateFacetRequest { + qt.aggregations = append(qt.aggregations, aggTest{fields, aggFacet}) return qt.q.AggregateFacet(fields...) - } // Merge 2 queries @@ -1201,6 +1375,9 @@ func getValues(item interface{}, fieldIdx [][]int) (ret []reflect.Value) { } func compareValues(t *testing.T, v1 reflect.Value, v2 reflect.Value) int { + if v2.Type().Kind() == reflect.Interface { + v2 = reflect.ValueOf(v2.Interface()) + } switch v1.Type().Kind() { case reflect.String: @@ -1376,7 +1553,7 @@ func (qt *queryTestEntryTree) getEntryByIndexName(index string) *queryTestEntry if entry := d.data.(*queryTestEntry); entry.index == index { return entry } - case twoFieldsEntry: + case twoFieldsEntry, alwaysTrue, alwaysFalse: return nil case bracket: t := d.data.(*queryTestEntryTree) @@ -1494,6 +1671,47 @@ func checkDWithin(point1 reindexer.Point, point2 reindexer.Point, distance float return (diffX*diffX + diffY*diffY) <= (distance * distance) } +func checkValue(t *testing.T, v reflect.Value, cond int, keys []reflect.Value) bool { + if cond == reindexer.RANGE { + if len(keys) != 2 { + panic("expected 2 keys in range condition") + } + return compareValues(t, v, keys[0]) >= 0 && compareValues(t, v, keys[1]) <= 0 + } else { + for _, k := range keys { + switch cond { + case reindexer.EQ, reindexer.SET: + if compareValues(t, v, k) == 0 { + return true + } + case reindexer.GT: + if compareValues(t, v, k) > 0 { + return true + } + case reindexer.GE: + if compareValues(t, v, k) >= 0 { + return true + } + case reindexer.LT: + if compareValues(t, v, k) < 0 { + return true + } + case reindexer.LE: + if compareValues(t, v, k) <= 0 { + return true + } + case reindexer.LIKE: + if likeValues(v, k) { + return true + } + default: + panic("Unsupported condition") + } + } + } + return false +} + func checkCondition(t *testing.T, ns *testNamespace, cond *queryTestEntry, item interface{}) bool { vals := getValues(item, cond.fieldIdx) @@ -1512,36 +1730,8 @@ func checkCondition(t *testing.T, ns *testNamespace, cond *queryTestEntry, item } for _, v := range vals { - if cond.condition == reindexer.RANGE { - if len(cond.keys) != 2 { - panic("expected 2 keys in range condition") - } - if compareValues(t, v, cond.keys[0]) >= 0 && compareValues(t, v, cond.keys[1]) <= 0 { - return true - } - } else { - for _, k := range cond.keys { - var found bool - switch cond.condition { - case reindexer.EQ, reindexer.SET: - found = compareValues(t, v, k) == 0 - case reindexer.GT: - found = compareValues(t, v, k) > 0 - case reindexer.GE: - found = compareValues(t, v, k) >= 0 - case reindexer.LT: - found = compareValues(t, v, k) < 0 - case reindexer.LE: - found = compareValues(t, v, k) <= 0 - case reindexer.LIKE: - found = likeValues(v, k) - default: - panic("Unsupported condition") - } - if found { - return true - } - } + if checkValue(t, v, cond.condition, cond.keys) { + return true } } return false @@ -1686,6 +1876,10 @@ func (qt *queryTestEntryTree) verifyConditions(t *testing.T, ns *testNamespace, case bracket: tree := cond.data.(*queryTestEntryTree) curFound = tree.verifyConditions(t, ns, item) + case alwaysTrue: + curFound = true + case alwaysFalse: + curFound = false } switch cond.op { case opNOT: diff --git a/test/reindexer_test.go b/test/reindexer_test.go index 6a1f03cd8..e59581519 100644 --- a/test/reindexer_test.go +++ b/test/reindexer_test.go @@ -30,6 +30,8 @@ var benchmarkSeedCount = flag.Int("seedcount", 500000, "count of items for bench var benchmarkSeedCPU = flag.Int("seedcpu", 1, "number threads of for seeding") var benchmarkSeed = flag.Int64("seed", time.Now().Unix(), "seed number for random") +var testLogger *TestLogger + func TestMain(m *testing.M) { flag.Parse() @@ -39,6 +41,10 @@ func TestMain(m *testing.M) { panic(err) } + if testing.Verbose() { + testLogger = &TestLogger{} + } + opts := []interface{}{} if udsn.Scheme == "builtin" { os.RemoveAll("/tmp/reindex_test/") @@ -58,9 +64,7 @@ func TestMain(m *testing.M) { DB.AddSlave(*dsnSlave, *slaveCount, reindexer.WithCreateDBIfMissing()) } - if testing.Verbose() { - DB.SetLogger(&TestLogger{}) - } + DB.SetLogger(testLogger) for k, v := range tnamespaces { DB.DropNamespace(k) diff --git a/test/slave_empty_storage_test.go b/test/slave_empty_storage_test.go index 3c05a0bad..7f4d889ef 100644 --- a/test/slave_empty_storage_test.go +++ b/test/slave_empty_storage_test.go @@ -21,7 +21,7 @@ func TestSlaveEmptyStorage(t *testing.T) { cfgMaster := config.DefaultServerConfig() cfgMaster.Net.HTTPAddr = "0:29088" cfgMaster.Net.RPCAddr = "0:26534" - cfgMaster.Storage.Path = "/tmp/rx_master1" + cfgMaster.Storage.Path = "/tmp/reindex_master1" os.RemoveAll(cfgMaster.Storage.Path) rxMaster := reindexer.NewReindex("builtinserver://xxx", reindexer.WithServerConfig(time.Second*100, cfgMaster)) { @@ -45,7 +45,7 @@ namespaces: []` cfgSlave := config.DefaultServerConfig() cfgSlave.Net.HTTPAddr = "0:29089" cfgSlave.Net.RPCAddr = "0:26535" - cfgSlave.Storage.Path = "/tmp/rx_slave2" + cfgSlave.Storage.Path = "/tmp/reindex_slave2" os.RemoveAll(cfgSlave.Storage.Path) rxSlave := reindexer.NewReindex("builtinserver://xxx", reindexer.WithServerConfig(time.Second*100, cfgSlave)) { diff --git a/test/update_test.go b/test/update_test.go index 395d5ca69..32949b81f 100644 --- a/test/update_test.go +++ b/test/update_test.go @@ -13,13 +13,20 @@ import ( ) const ( - fieldsUpdateNs = "test_items_fields_update" - truncateNs = "test_truncate" - removeItemsNs = "test_remove_items" + fieldsUpdateNs = "test_items_fields_update" + truncateNs = "test_truncate" + removeItemsNs = "test_remove_items" + sparseArrItemNs = "sparse_array_updates" ) +type ItemWithSparseArray struct { + ID int64 `json:"id" reindex:"id,hash,pk"` + Array []int64 `json:"array_idx" reindex:"array_idx,hash,sparse"` +} + func init() { tnamespaces["test_items_insert_update"] = TestItemSimple{} + tnamespaces[sparseArrItemNs] = ItemWithSparseArray{} } var checkInsertUpdateExistsData = []*TestItemSimple{ @@ -1017,3 +1024,28 @@ func TestTruncateNamespace(t *testing.T) { require.NoError(t, DB.OpenNamespace(truncateNs, nsOpts, TestItemComplexObject{})) checkItemsCount(t, truncateNs, 0) } + +func TestUpdateSparseArrayIndex(t *testing.T) { + emptyItem := &ItemWithSparseArray{ + ID: int64(2), + } + + item := &ItemWithSparseArray{ + ID: int64(2), + Array: []int64{1, 2, 3}, + } + + require.NoError(t, DB.Upsert(sparseArrItemNs, emptyItem)) + + require.NoError(t, DB.Upsert(sparseArrItemNs, emptyItem)) + results := DB.ExecSQL("SELECT * FROM " + sparseArrItemNs + " WHERE id = 2") + checkResultItem(t, results, emptyItem) + + require.NoError(t, DB.Upsert(sparseArrItemNs, item)) + results = DB.ExecSQL("SELECT * FROM " + sparseArrItemNs + " WHERE id = 2") + checkResultItem(t, results, item) + + require.NoError(t, DB.Upsert(sparseArrItemNs, emptyItem)) + results = DB.ExecSQL("SELECT * FROM " + sparseArrItemNs + " WHERE id = 2") + checkResultItem(t, results, emptyItem) +} diff --git a/test/uuid_test.go b/test/uuid_test.go index 699cbab73..4316030e3 100644 --- a/test/uuid_test.go +++ b/test/uuid_test.go @@ -415,17 +415,17 @@ func TestUuidClientBuiltinserver(t *testing.T) { ns := "test_uuid_builtinserver_connect" t.Run("test add uuid index on non-indexed string", func(t *testing.T) { - path1 := "/tmp/rx_uuid11" + path1 := "/tmp/reindex_uuid11" rx1 := configureAndStartServer("0:29188", "0:26634", path1) defer rx1.Close() { - f, err := os.OpenFile("/tmp/rx_uuid11"+"/uudb/replication.conf", os.O_RDWR|os.O_CREATE, 0644) + f, err := os.OpenFile("/tmp/reindex_uuid11"+"/uudb/replication.conf", os.O_RDWR|os.O_CREATE, 0644) assert.NoError(t, err) _, err = f.Write([]byte(masterConfig)) assert.NoError(t, err) } - path2 := "/tmp/rx_uuid12" + path2 := "/tmp/reindex_uuid12" rx2 := configureAndStartServer("0:29189", "0:26635", path2) defer rx2.Close() { @@ -486,7 +486,7 @@ func TestUuidClientBuiltinserver(t *testing.T) { }) t.Run("test update index from string to uuid", func(t *testing.T) { - path1 := "/tmp/rx_uuid11" + path1 := "/tmp/reindex_uuid11" rx1 := configureAndStartServer("0:29188", "0:26634", path1) defer rx1.Close() { @@ -496,7 +496,7 @@ func TestUuidClientBuiltinserver(t *testing.T) { assert.NoError(t, err) } - path2 := "/tmp/rx_uuid12" + path2 := "/tmp/reindex_uuid12" rx2 := configureAndStartServer("0:29189", "0:26635", path2) defer rx2.Close() {