1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-09 09:35:00 +09:00

[GO-678-dep-licence] Merge branch 'master' into GO-678-dep-licence

This commit is contained in:
Pavel Zavyalov 2023-01-19 16:33:52 +06:00
commit ee9c6944d2
No known key found for this signature in database
GPG key ID: D12476F8A1107A26
60 changed files with 29839 additions and 5965 deletions

View file

@ -18,7 +18,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v1
with:
go-version: 1.18.8
go-version: 1.18.10
- name: Setup GO
run: |
echo GOPATH=$(go env GOPATH) >> $GITHUB_ENV
@ -38,10 +38,9 @@ jobs:
curl https://raw.githubusercontent.com/Homebrew/homebrew-core/31b24d65a7210ea0a5689d5ad00dd8d1bf5211db/Formula/protobuf.rb --output protobuf.rb
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install ./protobuf.rb
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install --ignore-dependencies swift-protobuf
HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install mingw-w64
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install mingw-w64
brew tap filosottile/musl-cross
brew install filosottile/musl-cross/musl-cross -h
brew install filosottile/musl-cross/musl-cross --with-aarch64
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install filosottile/musl-cross/musl-cross
npm i -g node-gyp
- name: Checkout
uses: actions/checkout@v2
@ -76,8 +75,6 @@ jobs:
echo $FLAGS
mkdir -p .release
gox -cgo -ldflags="$FLAGS" -osarch="darwin/amd64 darwin/arm64" --tags="nographviz nowatchdog nosigar nomutexdeadlockdetector" -output="{{.OS}}-{{.Arch}}" github.com/anytypeio/go-anytype-middleware/cmd/grpcserver
CC="x86_64-linux-musl-gcc" CXX="x86_64-linux-musl-g++" gox -cgo -osarch="linux/amd64" --tags="nographviz nowatchdog nosigar nomutexdeadlockdetector" -output="{{.OS}}-{{.Arch}}" github.com/anytypeio/go-anytype-middleware/cmd/grpcserver
CC="aarch64-linux-musl-gcc" CXX="aarch64-linux-musl-g++" gox -cgo -osarch="linux/arm64" --tags="nographviz nowatchdog nosigar nomutexdeadlockdetector" -output="{{.OS}}-{{.Arch}}" github.com/anytypeio/go-anytype-middleware/cmd/grpcserver
make protos-server
CC="x86_64-w64-mingw32-gcc" CXX="x86_64-w64-mingw32-g++" gox -cgo -ldflags="$FLAGS" -osarch="windows/amd64" --tags="nographviz nowatchdog nosigar nomutexdeadlockdetector" -output="{{.OS}}-{{.Arch}}" github.com/anytypeio/go-anytype-middleware/cmd/grpcserver
ls -lha .
@ -109,7 +106,7 @@ jobs:
done
- name: Pack server unix
run: |
declare -a arr=("darwin-amd64" "darwin-arm64" "linux-amd64")
declare -a arr=("darwin-amd64" "darwin-arm64")
for i in "${arr[@]}"
do
OSARCH=${i%.*}
@ -154,6 +151,99 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_USER: ${{ github.actor }}
- name: Release
uses: softprops/action-gh-release@v1
with:
prerelease: ${{ contains(github.ref, '-rc') }}
fail_on_unmatched_files: true
files: '.release/*'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build_linux:
runs-on: ubuntu-22.04
steps:
- name: Install Go
uses: actions/setup-go@v1
with:
go-version: 1.18.10
- name: Setup GO
run: |
echo GOPATH=$(go env GOPATH) >> $GITHUB_ENV
echo GOBIN=$(go env GOPATH)/bin >> $GITHUB_ENV
echo $(go env GOPATH)/bin >> $GITHUB_PATH
- name: Install patched gox
run: |
mkdir -p $GOPATH/src/github.com/mitchellh
cd $GOPATH/src/github.com/mitchellh
git clone https://github.com/aslakhellesoy/gox
cd gox
git fetch
git checkout db6184738b77fbd5089e5fa1112177f391c91b24
go install github.com/mitchellh/gox
- name: Apt install and node deps
run: |
sudo apt update
sudo apt install -y protobuf-compiler libprotoc-dev gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
npm i -g node-gyp
- name: Checkout
uses: actions/checkout@v2
- name: Set env vars
run: |
export COMMIT=${GITHUB_SHA::7} >> $GITHUB_ENV
export GIT_SUMMARY=$(git describe --tags --dirty --always) >> $GITHUB_ENV
export DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") >> $GITHUB_ENV
export GIT_BRANCH=$(git branch --show-current)
echo "FLAGS=-X github.com/anytypeio/go-anytype-middleware/app.GitSummary=${GIT_SUMMARY} -X github.com/anytypeio/go-anytype-middleware/app.BuildDate=${DATE} -X github.com/anytypeio/go-anytype-middleware/app.GitCommit=${COMMIT} -X github.com/anytypeio/go-anytype-middleware/app.GitBranch=${GIT_BRANCH} -X github.com/anytypeio/go-anytype-middleware/app.GitState=clean" >> $GITHUB_ENV
echo VERSION=${GITHUB_REF##*/} >> $GITHUB_ENV
- name: install protoc
run: |
HAS_SYSTEM_PROTOBUF=false make setup-protoc
- name: setup go
run: |
make setup-go
- uses: actions/cache@v3
with:
path: |
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ matrix.go-version }}-
- name: Go mod download
run: |
go mod download
- name: Cross-compile library for linux amd64/arm64
run: |
echo $FLAGS
mkdir -p .release
gox -cgo -osarch="linux/amd64" -ldflags="$FLAGS" --tags="nographviz nowatchdog nosigar nomutexdeadlockdetector" -output="{{.OS}}-{{.Arch}}" github.com/anytypeio/go-anytype-middleware/cmd/grpcserver
CC=aarch64-linux-gnu-gcc gox -cgo -osarch="linux/arm64" -ldflags="$FLAGS" --tags="nographviz nowatchdog nosigar nomutexdeadlockdetector" -output="{{.OS}}-{{.Arch}}" github.com/anytypeio/go-anytype-middleware/cmd/grpcserver
make protos-server
- name: Make JS protos
run: |
make protos-js
mv dist/js/pb protobuf
mkdir -p protobuf/protos
cp pb/protos/*.proto ./protobuf/protos
cp pb/protos/service/*.proto ./protobuf/protos
cp pkg/lib/pb/model/protos/*.proto ./protobuf/protos
- name: Upload protobuf artifact for linux build
uses: actions/upload-artifact@v2
with:
name: libs
path: |
protobuf
if-no-files-found: error
retention-days: 1
- name: Pack server unix
run: |
declare -a arr=("linux-amd64" "linux-arm64")
for i in "${arr[@]}"
do
OSARCH=${i%.*}
cp ./${i}* ./grpc-server
tar -czf js_${VERSION}_${OSARCH}.tar.gz grpc-server protobuf
mv js_${VERSION}_${OSARCH}.tar.gz .release/
done
- name: Release
uses: softprops/action-gh-release@v1
with:

View file

@ -43,7 +43,7 @@ linters:
- gosec
- interfacebloat
- importas
- lll
# - lll
- misspell
- nestif
- prealloc

View file

@ -25,213 +25,229 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
func init() { proto.RegisterFile("pb/protos/service/service.proto", fileDescriptor_93a29dc403579097) }
var fileDescriptor_93a29dc403579097 = []byte{
// 3292 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x9c, 0xdf, 0x6f, 0x1d, 0x47,
0x15, 0xc7, 0x7b, 0x5f, 0x28, 0x6c, 0x69, 0x81, 0x2d, 0x84, 0x12, 0x5a, 0x27, 0x4d, 0x9b, 0xd8,
0x8e, 0xe3, 0x6b, 0x37, 0x81, 0x16, 0x78, 0x41, 0x37, 0x76, 0x9c, 0x58, 0x8d, 0x93, 0xe0, 0xeb,
0x24, 0x52, 0x25, 0x24, 0xd6, 0xbb, 0x93, 0xeb, 0xc5, 0x7b, 0x77, 0x96, 0xdd, 0xb9, 0xd7, 0x31,
0x08, 0x04, 0x02, 0x81, 0x40, 0x08, 0x2a, 0xc1, 0x1b, 0xff, 0x10, 0x8f, 0x7d, 0xe4, 0x11, 0xb5,
0xff, 0x08, 0xda, 0xdd, 0x33, 0xbf, 0xce, 0xce, 0x99, 0x5d, 0xf3, 0x54, 0xb8, 0xe7, 0x73, 0xce,
0x77, 0x7e, 0xcf, 0x99, 0x99, 0x8d, 0x83, 0x2b, 0xc5, 0xf1, 0x56, 0x51, 0x72, 0xc1, 0xab, 0xad,
0x8a, 0x95, 0xcb, 0x34, 0x66, 0xf2, 0xbf, 0xe3, 0xe6, 0xe7, 0xf0, 0xd5, 0x28, 0x3f, 0x17, 0xe7,
0x05, 0xbb, 0xfc, 0x96, 0x26, 0x63, 0x3e, 0x9f, 0x47, 0x79, 0x52, 0xb5, 0xc8, 0xe5, 0x4b, 0xda,
0xc2, 0x96, 0x2c, 0x17, 0xf0, 0xfb, 0xed, 0x4f, 0xff, 0x36, 0x0a, 0xde, 0xd8, 0xc9, 0x52, 0x96,
0x8b, 0x1d, 0xf0, 0x08, 0x3f, 0x09, 0x5e, 0x9f, 0x14, 0xc5, 0x7d, 0x26, 0x9e, 0xb1, 0xb2, 0x4a,
0x79, 0x1e, 0xbe, 0x37, 0x06, 0x81, 0xf1, 0x61, 0x11, 0x8f, 0x27, 0x45, 0x31, 0xd6, 0xc6, 0xf1,
0x21, 0xfb, 0xc5, 0x82, 0x55, 0xe2, 0xf2, 0xfb, 0x7e, 0xa8, 0x2a, 0x78, 0x5e, 0xb1, 0xf0, 0x45,
0xf0, 0x8d, 0x49, 0x51, 0x4c, 0x99, 0xd8, 0x65, 0x75, 0x05, 0xa6, 0x22, 0x12, 0x2c, 0x5c, 0xed,
0xb8, 0xda, 0x80, 0xd2, 0x58, 0xeb, 0x07, 0x41, 0xe7, 0x28, 0x78, 0xad, 0xd6, 0x39, 0x59, 0x88,
0x84, 0x9f, 0xe5, 0xe1, 0xbb, 0x5d, 0x47, 0x30, 0xa9, 0xd8, 0xd7, 0x7c, 0x08, 0x44, 0x7d, 0x1e,
0x7c, 0xf5, 0x79, 0x94, 0x65, 0x4c, 0xec, 0x94, 0xac, 0x2e, 0xb8, 0xed, 0xd3, 0x9a, 0xc6, 0xad,
0x4d, 0xc5, 0x7d, 0xcf, 0xcb, 0x40, 0xe0, 0x4f, 0x82, 0xd7, 0x5b, 0xcb, 0x21, 0x8b, 0xf9, 0x92,
0x95, 0xa1, 0xd3, 0x0b, 0x8c, 0x44, 0x93, 0x77, 0x20, 0x1c, 0x7b, 0x87, 0xe7, 0x4b, 0x56, 0x0a,
0x77, 0x6c, 0x30, 0xfa, 0x63, 0x6b, 0x08, 0x62, 0x67, 0xc1, 0x9b, 0x66, 0x83, 0x4c, 0x59, 0xd5,
0x0c, 0x98, 0x75, 0xba, 0xce, 0x80, 0x28, 0x9d, 0x9b, 0x43, 0x50, 0x50, 0x4b, 0x83, 0x10, 0xd4,
0x32, 0x5e, 0x29, 0xb1, 0x35, 0x67, 0x04, 0x83, 0x50, 0x5a, 0xeb, 0x03, 0x48, 0x90, 0xfa, 0x59,
0xf0, 0xb5, 0xe7, 0xbc, 0x3c, 0xad, 0x8a, 0x28, 0x66, 0xd0, 0xd9, 0xd7, 0x6d, 0x6f, 0x69, 0xc5,
0xfd, 0x7d, 0xa3, 0x0f, 0x03, 0x85, 0xd3, 0x20, 0x54, 0xc6, 0xc7, 0xc7, 0x3f, 0x67, 0xb1, 0x98,
0x24, 0x09, 0x6e, 0x39, 0xe5, 0xdd, 0x12, 0xe3, 0x49, 0x92, 0x50, 0x2d, 0xe7, 0x46, 0x41, 0xec,
0x2c, 0xb8, 0x84, 0xc4, 0x1e, 0xa6, 0x55, 0x23, 0xb8, 0xe9, 0x8f, 0x02, 0x98, 0x12, 0x1d, 0x0f,
0xc5, 0x41, 0xf8, 0xb7, 0xa3, 0xe0, 0x3b, 0x0e, 0xe5, 0x43, 0x36, 0xe7, 0x4b, 0x16, 0x6e, 0xf7,
0x47, 0x6b, 0x49, 0xa5, 0xff, 0xc1, 0x05, 0x3c, 0x1c, 0x5d, 0x39, 0x65, 0x19, 0x8b, 0x05, 0xd9,
0x95, 0xad, 0xb9, 0xb7, 0x2b, 0x15, 0x66, 0xcc, 0x02, 0x69, 0xbc, 0xcf, 0xc4, 0xce, 0xa2, 0x2c,
0x59, 0x2e, 0xc8, 0xbe, 0xd4, 0x48, 0x6f, 0x5f, 0x5a, 0xa8, 0xa3, 0x3e, 0xf7, 0x99, 0x98, 0x64,
0x19, 0x59, 0x9f, 0xd6, 0xdc, 0x5b, 0x1f, 0x85, 0x81, 0xc2, 0x6f, 0x8c, 0x3e, 0x9b, 0x32, 0xb1,
0x5f, 0x3d, 0x48, 0x67, 0x27, 0x59, 0x3a, 0x3b, 0x11, 0x2c, 0x09, 0xb7, 0xc8, 0x46, 0xb1, 0x41,
0xa5, 0xba, 0x3d, 0xdc, 0xc1, 0x51, 0xc3, 0x7b, 0x2f, 0x0b, 0x5e, 0xd2, 0x3d, 0xd6, 0x9a, 0x7b,
0x6b, 0xa8, 0x30, 0x50, 0xf8, 0x69, 0xf0, 0xc6, 0x24, 0x8e, 0xf9, 0x22, 0x57, 0x0b, 0x2e, 0xda,
0xbe, 0x5a, 0x63, 0x67, 0xc5, 0xbd, 0xde, 0x43, 0xe9, 0x25, 0x17, 0x6c, 0xb0, 0x76, 0xbc, 0xe7,
0xf4, 0x43, 0x2b, 0xc7, 0xfb, 0x7e, 0xa8, 0x13, 0x7b, 0x97, 0x65, 0x8c, 0x8c, 0xdd, 0x1a, 0x7b,
0x62, 0x2b, 0xa8, 0x13, 0x1b, 0x26, 0x8a, 0x3b, 0x36, 0x9a, 0x26, 0xef, 0xfb, 0x21, 0x63, 0x47,
0x86, 0xd8, 0x82, 0x17, 0x78, 0x47, 0x96, 0x4e, 0x82, 0x17, 0xd4, 0x8e, 0x6c, 0x23, 0x9d, 0xa8,
0x07, 0xf5, 0x82, 0xe2, 0x8e, 0x7a, 0x60, 0xae, 0x20, 0xd7, 0x7c, 0x88, 0x9e, 0xd0, 0xb2, 0xff,
0x78, 0xfe, 0x22, 0x9d, 0x3d, 0x2d, 0x92, 0xba, 0x17, 0xd7, 0xdd, 0x1d, 0x64, 0x20, 0xc4, 0x84,
0x26, 0x50, 0x50, 0xfb, 0x49, 0x10, 0xb4, 0xcb, 0xd7, 0xe3, 0x82, 0xe5, 0xe1, 0x55, 0xcb, 0x13,
0xd6, 0xb5, 0xda, 0xa2, 0x62, 0xbf, 0xeb, 0x21, 0x74, 0xb3, 0xb4, 0xbf, 0x37, 0xbb, 0x5b, 0xe8,
0xf4, 0x68, 0x4c, 0x44, 0xb3, 0x20, 0x04, 0x17, 0x74, 0x7a, 0xc2, 0xcf, 0xdc, 0x05, 0xad, 0x2d,
0xfe, 0x82, 0x02, 0xa1, 0x33, 0x2a, 0x28, 0xa8, 0x2b, 0xa3, 0x92, 0xc5, 0xf0, 0x65, 0x54, 0x98,
0x81, 0xc0, 0x3c, 0xf8, 0xa6, 0x19, 0xf8, 0x2e, 0xe7, 0xa7, 0xf3, 0xa8, 0x3c, 0x0d, 0x6f, 0xd2,
0xce, 0x92, 0x51, 0x42, 0x1b, 0x83, 0x58, 0xbd, 0x68, 0x99, 0x82, 0x53, 0x86, 0x17, 0x2d, 0xcb,
0x7f, 0xca, 0xa8, 0x45, 0xcb, 0x81, 0xe1, 0x4e, 0xbd, 0x5f, 0x46, 0xc5, 0x89, 0xbb, 0x53, 0x1b,
0x93, 0xbf, 0x53, 0x25, 0x82, 0x7b, 0x60, 0xca, 0xa2, 0x32, 0x3e, 0x71, 0xf7, 0x40, 0x6b, 0xf3,
0xf7, 0x80, 0x62, 0x20, 0x70, 0x19, 0x7c, 0xcb, 0x0c, 0x3c, 0x5d, 0x1c, 0x57, 0x71, 0x99, 0x1e,
0xb3, 0x70, 0x83, 0xf6, 0x56, 0x90, 0x92, 0xba, 0x35, 0x0c, 0xd6, 0x19, 0x22, 0x68, 0x4a, 0xdb,
0x7e, 0x52, 0xa1, 0x0c, 0x51, 0xc6, 0x30, 0x08, 0x22, 0x43, 0x74, 0x93, 0xb8, 0x7a, 0xf7, 0x4b,
0xbe, 0x28, 0xaa, 0x9e, 0xea, 0x21, 0xc8, 0x5f, 0xbd, 0x2e, 0x0c, 0x9a, 0x2f, 0x83, 0x6f, 0x9b,
0x4d, 0xfa, 0x34, 0xaf, 0x94, 0xea, 0x26, 0xdd, 0x4e, 0x06, 0x46, 0xe4, 0x71, 0x1e, 0x1c, 0x94,
0xe3, 0xe0, 0xeb, 0x52, 0x59, 0xec, 0x32, 0x11, 0xa5, 0x59, 0x15, 0xde, 0x70, 0xc7, 0x90, 0x76,
0xa5, 0xb5, 0xda, 0xcb, 0xe1, 0x29, 0xb4, 0xbb, 0x28, 0xb2, 0x34, 0xee, 0x26, 0xdd, 0xe0, 0xab,
0xcc, 0xfe, 0x29, 0x64, 0x62, 0x7a, 0x61, 0x57, 0xd5, 0x68, 0xff, 0xc7, 0xd1, 0x79, 0x81, 0x17,
0x76, 0x5d, 0x42, 0x8d, 0x10, 0x0b, 0x3b, 0x81, 0xe2, 0xfa, 0x4c, 0x99, 0x78, 0x18, 0x9d, 0xf3,
0x05, 0xb1, 0x24, 0x28, 0xb3, 0xbf, 0x3e, 0x26, 0x06, 0x0a, 0x8b, 0xe0, 0x92, 0x52, 0xd8, 0xcf,
0x05, 0x2b, 0xf3, 0x28, 0xdb, 0xcb, 0xa2, 0x59, 0x15, 0x12, 0xf3, 0xc6, 0xa6, 0x94, 0xde, 0xe6,
0x40, 0xda, 0xd1, 0x8c, 0xfb, 0xd5, 0x5e, 0xb4, 0xe4, 0x65, 0x2a, 0xe8, 0x66, 0xd4, 0x48, 0x6f,
0x33, 0x5a, 0xa8, 0x53, 0x6d, 0x52, 0xc6, 0x27, 0xe9, 0x92, 0x25, 0x1e, 0x35, 0x89, 0x0c, 0x50,
0x33, 0x50, 0xac, 0x56, 0x9f, 0x25, 0xf4, 0x40, 0x74, 0xaa, 0x59, 0x88, 0x5f, 0x0d, 0xa3, 0x78,
0x5e, 0x35, 0xf6, 0x36, 0xa1, 0xbb, 0x41, 0xfa, 0xdb, 0x39, 0xdd, 0x6a, 0x2f, 0x87, 0x97, 0x8d,
0xda, 0x68, 0x37, 0xe2, 0x26, 0x15, 0xc3, 0xdd, 0x90, 0xe3, 0xa1, 0x38, 0xa9, 0xac, 0x06, 0x8b,
0x5f, 0xb9, 0x33, 0x60, 0xc6, 0x43, 0x71, 0xdc, 0x8d, 0x93, 0xa2, 0xc8, 0xce, 0x8f, 0xd8, 0xbc,
0xc8, 0xc8, 0x6e, 0xb4, 0x10, 0x7f, 0x37, 0x62, 0x14, 0x6f, 0xcd, 0x47, 0xbc, 0xde, 0xf8, 0x9d,
0x5b, 0x73, 0x63, 0xf2, 0x6f, 0xcd, 0x12, 0xc1, 0x5b, 0xcc, 0x24, 0x49, 0x9e, 0xa7, 0xe2, 0xa4,
0xfd, 0x3f, 0xfb, 0x89, 0x7b, 0x8b, 0x41, 0x90, 0x7f, 0x8b, 0xe9, 0xc2, 0xfa, 0x82, 0x4e, 0xe6,
0x78, 0x51, 0xc9, 0xee, 0x9e, 0x3f, 0x4c, 0xf3, 0xd3, 0xd0, 0xbd, 0x82, 0x6b, 0x80, 0xb8, 0xa0,
0x73, 0x82, 0xb8, 0x6e, 0x75, 0xe2, 0x7a, 0xb7, 0x64, 0x51, 0x12, 0x97, 0x8b, 0xf9, 0x71, 0xe5,
0xae, 0x1b, 0x82, 0xfc, 0x75, 0xeb, 0xc2, 0x38, 0x27, 0x9c, 0x32, 0x61, 0x4a, 0x52, 0xcb, 0x83,
0x4b, 0x71, 0x63, 0x10, 0x8b, 0x13, 0xe6, 0xa7, 0x79, 0xc2, 0xdd, 0x09, 0x73, 0x6d, 0xf1, 0x27,
0xcc, 0x40, 0xe0, 0x90, 0x87, 0x8c, 0x0a, 0x59, 0x5b, 0xfc, 0x21, 0x81, 0x70, 0xad, 0x41, 0x70,
0xde, 0x26, 0xd7, 0x20, 0x74, 0xe0, 0x5e, 0xed, 0xe5, 0xf0, 0x7c, 0x94, 0x99, 0xf3, 0x1e, 0x13,
0xf1, 0x89, 0x7b, 0x3e, 0x5a, 0x88, 0x7f, 0x3e, 0x62, 0x14, 0x57, 0xe9, 0x88, 0xab, 0xcc, 0xff,
0x86, 0x7b, 0xc6, 0x75, 0xb2, 0xfe, 0xd5, 0x5e, 0x0e, 0x67, 0xce, 0xfb, 0xf3, 0xa6, 0xcd, 0x9c,
0x53, 0xba, 0xb5, 0xf9, 0x33, 0x67, 0xc5, 0xe0, 0xd2, 0xb7, 0x86, 0xba, 0x39, 0xdd, 0xa5, 0xd7,
0x76, 0x7f, 0xe9, 0x2d, 0x0e, 0x44, 0xfe, 0x39, 0x0a, 0xae, 0x98, 0x2a, 0x8f, 0xb8, 0x48, 0x79,
0xfe, 0x2c, 0xca, 0xd2, 0xfa, 0x74, 0x7a, 0xc4, 0x4f, 0x59, 0x1e, 0x7e, 0xe4, 0x29, 0x6d, 0xcb,
0x8f, 0x2d, 0x07, 0x55, 0x8a, 0x1f, 0x5c, 0xdc, 0xd1, 0x7d, 0x6e, 0x3b, 0x64, 0x59, 0x54, 0xe3,
0xbe, 0x73, 0x9b, 0x64, 0x86, 0x9c, 0xdb, 0x0c, 0x16, 0x04, 0x7f, 0x37, 0x0a, 0x2e, 0xbb, 0x14,
0x1f, 0x17, 0x8d, 0xee, 0x76, 0x7f, 0xac, 0x96, 0x24, 0xae, 0x28, 0xfd, 0x1e, 0x50, 0x86, 0x5f,
0x05, 0x6f, 0x49, 0x93, 0xbe, 0xc1, 0x84, 0x02, 0xd8, 0x1b, 0x9f, 0x2a, 0x3f, 0xe6, 0x94, 0xfc,
0xd6, 0x60, 0x5e, 0x67, 0xa9, 0x76, 0xb9, 0x2a, 0x94, 0xa5, 0xaa, 0x18, 0x60, 0x26, 0xb2, 0x54,
0x07, 0x86, 0xf7, 0x14, 0x89, 0x4c, 0x92, 0xc4, 0xb9, 0xa7, 0xa8, 0x10, 0xe6, 0x95, 0xf3, 0x5a,
0x3f, 0x88, 0xc7, 0x8e, 0x34, 0x43, 0x42, 0x75, 0xd3, 0x17, 0x01, 0x25, 0x55, 0x1b, 0x83, 0x58,
0x7d, 0x51, 0xda, 0xa9, 0xd8, 0x1e, 0x8b, 0xc4, 0xa2, 0xec, 0x5c, 0x94, 0x76, 0xcb, 0x2d, 0x41,
0xe2, 0xa2, 0xd4, 0xeb, 0x00, 0xfa, 0x7f, 0x1a, 0x05, 0x6f, 0xdb, 0x5c, 0xdb, 0xc5, 0xaa, 0x0c,
0xb7, 0x7d, 0x21, 0x6d, 0x56, 0x15, 0xe3, 0xce, 0x85, 0x7c, 0xa0, 0x24, 0x7f, 0x18, 0x05, 0xdf,
0xb5, 0xd1, 0xe6, 0x29, 0x60, 0x19, 0xa5, 0x59, 0x74, 0x9c, 0xb1, 0xf0, 0x03, 0x5f, 0x50, 0x0b,
0x55, 0xe5, 0xb8, 0x7d, 0x11, 0x17, 0x7c, 0x1e, 0x6a, 0xe7, 0x9b, 0x71, 0xc4, 0xbb, 0x45, 0xcf,
0x4a, 0xc7, 0x29, 0x6f, 0x73, 0x20, 0xad, 0x9f, 0x57, 0xf4, 0xcf, 0x66, 0x03, 0x38, 0xb3, 0x5c,
0xf0, 0x35, 0x6a, 0xe2, 0xcd, 0x72, 0x9d, 0x38, 0x08, 0x0b, 0x99, 0x45, 0x99, 0xc2, 0xf5, 0xec,
0xba, 0xd5, 0x1b, 0xc8, 0x9c, 0x62, 0x9b, 0x03, 0x69, 0x50, 0xfd, 0x75, 0xf0, 0x56, 0x57, 0x15,
0x9e, 0x74, 0xb6, 0x7a, 0x43, 0xa1, 0x17, 0x9d, 0xed, 0xe1, 0x0e, 0xfa, 0x92, 0xe7, 0x41, 0x5a,
0x09, 0x5e, 0x9e, 0x4f, 0x4f, 0xf8, 0x99, 0x7c, 0xa4, 0xb6, 0x97, 0x09, 0x00, 0xc6, 0x06, 0x41,
0x5c, 0xf2, 0xb8, 0xc9, 0x8e, 0x94, 0x7e, 0xcc, 0xae, 0x08, 0x29, 0x83, 0xe8, 0x91, 0xb2, 0x49,
0xbd, 0x48, 0xca, 0x5a, 0xe9, 0x97, 0xf7, 0x55, 0x77, 0x51, 0xbb, 0xaf, 0xef, 0x6b, 0xfd, 0xa0,
0x3e, 0xaa, 0xec, 0xa5, 0x19, 0x7b, 0xfc, 0xe2, 0x45, 0xc6, 0xa3, 0x04, 0x1d, 0x55, 0x6a, 0xcb,
0x18, 0x4c, 0xc4, 0x51, 0x05, 0x21, 0x7a, 0x13, 0xa9, 0x0d, 0xf5, 0xe8, 0x94, 0x91, 0xaf, 0x77,
0xdd, 0x0c, 0x33, 0xb1, 0x89, 0x38, 0x30, 0x9d, 0xf8, 0xd6, 0xc6, 0xa7, 0x45, 0x13, 0xfc, 0x6a,
0xd7, 0xab, 0xb5, 0x10, 0x89, 0xaf, 0x4d, 0xe8, 0x04, 0xae, 0xfe, 0x7d, 0x97, 0x9f, 0xe5, 0x4d,
0x50, 0x47, 0x45, 0xa5, 0x8d, 0x48, 0xe0, 0x30, 0x03, 0x81, 0x3f, 0x0e, 0xbe, 0xdc, 0x04, 0x2e,
0x79, 0x11, 0xae, 0x38, 0x1c, 0x4a, 0xe3, 0x95, 0xe3, 0x0a, 0x69, 0xd7, 0x27, 0xa5, 0x47, 0xd1,
0x32, 0x9d, 0xa9, 0x45, 0xa5, 0x9d, 0x23, 0xf8, 0xa4, 0xa4, 0x99, 0xb1, 0x01, 0x11, 0x27, 0x25,
0x12, 0x06, 0xcd, 0x7f, 0x8c, 0x82, 0xab, 0x9a, 0xb9, 0x2f, 0xaf, 0xb7, 0xf6, 0xf3, 0x17, 0xbc,
0x3e, 0x36, 0xd6, 0x47, 0xb9, 0x2a, 0xfc, 0x90, 0x0a, 0xe9, 0xe6, 0x55, 0x51, 0x3e, 0xba, 0xb0,
0x9f, 0x4e, 0x93, 0xe4, 0xd1, 0xbb, 0x5d, 0x8b, 0xf7, 0x4a, 0x3e, 0x6f, 0x3d, 0x50, 0x9a, 0xa4,
0x4e, 0xe8, 0x98, 0x23, 0xd2, 0x24, 0x1f, 0x6f, 0xec, 0xb5, 0x94, 0x7a, 0xb3, 0xc3, 0xdc, 0x1e,
0x16, 0xd1, 0xda, 0x67, 0xee, 0x5c, 0xc8, 0x47, 0xbf, 0xd2, 0xa9, 0x82, 0x64, 0x3c, 0xc7, 0x2f,
0x80, 0x3a, 0x4a, 0x6d, 0x24, 0x5e, 0xe9, 0x3a, 0x90, 0x5e, 0x85, 0xa4, 0xa9, 0x3d, 0xc1, 0x4d,
0xb2, 0x0c, 0xad, 0x42, 0xca, 0x55, 0x01, 0xc4, 0x2a, 0xe4, 0x04, 0x41, 0xe7, 0x30, 0x78, 0xad,
0xee, 0xdc, 0x27, 0x25, 0x5b, 0xa6, 0x0c, 0xbf, 0x25, 0x19, 0x16, 0x62, 0x3a, 0xdb, 0x84, 0x7e,
0xd4, 0x7d, 0x9a, 0x57, 0x45, 0x16, 0x55, 0x27, 0xf0, 0x96, 0x61, 0xd7, 0x59, 0x1a, 0xf1, 0x6b,
0xc6, 0xf5, 0x1e, 0x4a, 0x9f, 0xca, 0xa4, 0x4d, 0xad, 0x18, 0x37, 0xdc, 0xae, 0x9d, 0x55, 0x63,
0xb5, 0x97, 0xd3, 0xab, 0xf3, 0xdd, 0x8c, 0xc7, 0xa7, 0xb0, 0xcc, 0xd9, 0xb5, 0x6e, 0x2c, 0x78,
0x9d, 0xbb, 0xe6, 0x43, 0xf4, 0x42, 0xd7, 0x18, 0x0e, 0x59, 0x91, 0x45, 0x31, 0x7e, 0x65, 0x6b,
0x7d, 0xc0, 0x46, 0x2c, 0x74, 0x98, 0x41, 0xc5, 0x85, 0xd7, 0x3b, 0x57, 0x71, 0xd1, 0xe3, 0xdd,
0x35, 0x1f, 0xa2, 0x97, 0xfa, 0xc6, 0x30, 0x2d, 0xb2, 0x54, 0xa0, 0xb1, 0xd1, 0x7a, 0x34, 0x16,
0x62, 0x6c, 0xd8, 0x04, 0x0a, 0x79, 0xc0, 0xca, 0x19, 0x73, 0x86, 0x6c, 0x2c, 0xde, 0x90, 0x92,
0x80, 0x90, 0x8f, 0x82, 0xaf, 0xb4, 0x75, 0xe7, 0xc5, 0x79, 0x78, 0xc5, 0x55, 0x2d, 0x5e, 0x9c,
0xab, 0x80, 0x57, 0x69, 0x00, 0x15, 0xf1, 0x49, 0x54, 0x09, 0x77, 0x11, 0x1b, 0x8b, 0xb7, 0x88,
0x92, 0xd0, 0xfb, 0x50, 0x5b, 0xc4, 0x85, 0x40, 0xfb, 0x10, 0x14, 0xc0, 0x78, 0x72, 0xb8, 0x42,
0xda, 0xf5, 0xf4, 0x6a, 0x7b, 0x85, 0x89, 0xbd, 0x94, 0x65, 0x49, 0x85, 0xa6, 0x17, 0xb4, 0xbb,
0xb4, 0x12, 0xd3, 0xab, 0x4b, 0xa1, 0xa1, 0x04, 0x17, 0x50, 0xae, 0xda, 0xa1, 0xbb, 0xa7, 0x6b,
0x3e, 0x44, 0xe7, 0x25, 0x8d, 0xc1, 0xb8, 0x5e, 0x77, 0x95, 0xc7, 0x71, 0xbb, 0x7e, 0xa3, 0x0f,
0x03, 0x85, 0xbf, 0x8c, 0x82, 0x77, 0x94, 0xc4, 0x01, 0x5f, 0xb2, 0x23, 0x7e, 0xef, 0x65, 0x5a,
0x89, 0x34, 0x9f, 0xc1, 0xd6, 0x74, 0x87, 0x88, 0xe4, 0x82, 0x95, 0xfc, 0xf7, 0x2e, 0xe6, 0xa4,
0x77, 0x48, 0x54, 0x96, 0x47, 0xec, 0xcc, 0xb9, 0x43, 0xe2, 0x88, 0x8a, 0x23, 0x76, 0x48, 0x1f,
0xaf, 0x4f, 0xc3, 0x4a, 0x1c, 0xbe, 0x14, 0x3c, 0xe2, 0x32, 0x59, 0xa1, 0xa2, 0x61, 0x90, 0x38,
0x17, 0x78, 0x1d, 0x74, 0xb2, 0xae, 0xf4, 0xf5, 0x20, 0x5d, 0x23, 0xe2, 0x74, 0x07, 0xea, 0xfa,
0x00, 0xd2, 0x21, 0xa5, 0xdf, 0x88, 0x28, 0xa9, 0xee, 0x13, 0xd1, 0xfa, 0x00, 0xd2, 0x38, 0x59,
0x9b, 0xd5, 0xba, 0x1b, 0xc5, 0xa7, 0xb3, 0x92, 0x2f, 0xf2, 0x64, 0x87, 0x67, 0xbc, 0x44, 0x27,
0x6b, 0xab, 0xd4, 0x08, 0x25, 0x4e, 0xd6, 0x3d, 0x2e, 0x3a, 0x31, 0x30, 0x4b, 0x31, 0xc9, 0xd2,
0x19, 0x3e, 0x9e, 0x58, 0x81, 0x1a, 0x80, 0x48, 0x0c, 0x9c, 0xa0, 0x63, 0x10, 0xb5, 0xc7, 0x17,
0x91, 0xc6, 0x51, 0xd6, 0xea, 0x6d, 0xd1, 0x61, 0x2c, 0xb0, 0x77, 0x10, 0x39, 0x1c, 0x1c, 0xf5,
0x3c, 0x5a, 0x94, 0xf9, 0x7e, 0x2e, 0x38, 0x59, 0x4f, 0x09, 0xf4, 0xd6, 0xd3, 0x00, 0x75, 0x36,
0xd1, 0x98, 0x8f, 0xd8, 0xcb, 0xba, 0x34, 0xf5, 0x7f, 0x42, 0xc7, 0x92, 0x53, 0xff, 0x3e, 0x06,
0x3b, 0x91, 0x4d, 0xb8, 0x38, 0x54, 0x19, 0x10, 0x69, 0x07, 0x8c, 0xc7, 0xdb, 0x1e, 0x26, 0x6b,
0xfd, 0xa0, 0x5b, 0x67, 0x2a, 0xce, 0x33, 0xe6, 0xd3, 0x69, 0x80, 0x21, 0x3a, 0x12, 0xd4, 0x8f,
0x08, 0x56, 0x7d, 0x4e, 0x58, 0x7c, 0xda, 0x79, 0x09, 0xb6, 0x0b, 0xda, 0x22, 0xc4, 0x23, 0x02,
0x81, 0xba, 0xbb, 0x68, 0x3f, 0xe6, 0xb9, 0xaf, 0x8b, 0x6a, 0xfb, 0x90, 0x2e, 0x02, 0x4e, 0x9f,
0xee, 0x94, 0x15, 0x46, 0x66, 0xdb, 0x4d, 0x1b, 0x44, 0x04, 0x13, 0x22, 0x4e, 0x77, 0x24, 0xac,
0xef, 0x49, 0xb1, 0xe6, 0x41, 0xf7, 0xdb, 0xa8, 0x4e, 0x94, 0x03, 0xfa, 0xdb, 0x28, 0x8a, 0xa5,
0x2b, 0xd9, 0x8e, 0x91, 0x9e, 0x28, 0xf6, 0x38, 0xb9, 0x35, 0x0c, 0xd6, 0x4f, 0xcf, 0x96, 0xe6,
0x4e, 0xc6, 0xa2, 0xb2, 0x55, 0xdd, 0xf4, 0x04, 0xd2, 0x18, 0x71, 0x29, 0xe7, 0xc1, 0xd1, 0x12,
0x66, 0x29, 0xef, 0xf0, 0x5c, 0xb0, 0x5c, 0xb8, 0x96, 0x30, 0x3b, 0x18, 0x80, 0xbe, 0x25, 0x8c,
0x72, 0x40, 0xe3, 0x76, 0x2f, 0xcd, 0xd8, 0x94, 0x89, 0x47, 0xd1, 0x9c, 0xb9, 0xc6, 0x6d, 0x73,
0xd5, 0x00, 0x76, 0xdf, 0xb8, 0x45, 0x1c, 0x9a, 0xf2, 0xfb, 0xf3, 0x68, 0xa6, 0x54, 0x1c, 0xde,
0x8d, 0xbd, 0x23, 0xb3, 0xd6, 0x0f, 0x22, 0x9d, 0x67, 0x69, 0xc2, 0xb8, 0x47, 0xa7, 0xb1, 0x0f,
0xd1, 0xc1, 0x20, 0xca, 0x9c, 0xea, 0xda, 0xb6, 0xe7, 0x91, 0x49, 0x9e, 0xc0, 0x29, 0x6c, 0x4c,
0x34, 0x0a, 0xe2, 0x7c, 0x99, 0x13, 0xc1, 0xa3, 0xf9, 0x21, 0xaf, 0xd0, 0x7c, 0xf3, 0x43, 0xdd,
0x90, 0x0d, 0x99, 0x1f, 0x2e, 0x18, 0x34, 0x7f, 0x09, 0xf3, 0x63, 0x37, 0x12, 0x51, 0x7d, 0x8e,
0x7e, 0x96, 0xb2, 0x33, 0x38, 0xc6, 0x39, 0xea, 0x2b, 0xa9, 0x71, 0x8d, 0xe1, 0x33, 0xdd, 0xd6,
0x60, 0xde, 0xa3, 0x0d, 0xd9, 0x79, 0xaf, 0x36, 0x4a, 0xd3, 0xb7, 0x06, 0xf3, 0x1e, 0x6d, 0xf8,
0xbe, 0xb7, 0x57, 0x1b, 0x7d, 0xe4, 0xbb, 0x35, 0x98, 0x07, 0xed, 0xdf, 0x8f, 0x82, 0xcb, 0x1d,
0xf1, 0x3a, 0x07, 0x8a, 0x45, 0xba, 0x64, 0xae, 0x54, 0xce, 0x8e, 0xa7, 0x50, 0x5f, 0x2a, 0x47,
0xbb, 0x40, 0x29, 0xfe, 0x3c, 0x0a, 0xde, 0x76, 0x95, 0xe2, 0x09, 0xaf, 0xd2, 0xe6, 0xc9, 0xf1,
0xce, 0x80, 0xa0, 0x12, 0xf6, 0x1d, 0x58, 0x7c, 0x4e, 0xfa, 0xc1, 0xc6, 0x42, 0xeb, 0x71, 0xca,
0x17, 0x65, 0x8c, 0x1f, 0x6c, 0xec, 0x78, 0x8a, 0x22, 0x5e, 0x30, 0x68, 0x5a, 0xbf, 0x60, 0x58,
0x8c, 0xf9, 0x74, 0xe2, 0xeb, 0x55, 0xe7, 0xeb, 0xc9, 0xf6, 0x70, 0x07, 0x90, 0xff, 0xa3, 0xcc,
0xe9, 0xb1, 0x3e, 0x4c, 0x82, 0xdb, 0x43, 0x22, 0xa2, 0x89, 0x70, 0xe7, 0x42, 0x3e, 0x50, 0x90,
0x7f, 0x8d, 0x82, 0x6b, 0xce, 0x82, 0xd8, 0xaf, 0x77, 0x3f, 0x1c, 0x12, 0xdb, 0xfd, 0x8a, 0xf7,
0xa3, 0xff, 0xc7, 0x15, 0x4a, 0xf7, 0x57, 0x79, 0xb4, 0x96, 0x1e, 0xcd, 0x87, 0xb1, 0x8f, 0xcb,
0x84, 0x95, 0x30, 0x63, 0x7d, 0x83, 0x4e, 0xc3, 0x78, 0xde, 0x7e, 0xff, 0x82, 0x5e, 0x50, 0x9c,
0xbf, 0x8f, 0x82, 0x15, 0x0b, 0x86, 0x0f, 0x98, 0x8c, 0xf2, 0xf8, 0x22, 0x1b, 0x34, 0x2e, 0xd0,
0x87, 0x17, 0x75, 0xc3, 0x19, 0x6a, 0xdd, 0x6e, 0xb0, 0x78, 0xbb, 0x32, 0xd4, 0xa6, 0x59, 0xd1,
0xa2, 0xbd, 0xda, 0xcb, 0xb9, 0x44, 0xee, 0xbd, 0x2c, 0xa2, 0x3c, 0xa1, 0x45, 0x5a, 0x7b, 0xbf,
0x88, 0xe2, 0x70, 0x66, 0x5f, 0x5b, 0x0f, 0xb9, 0xdc, 0x89, 0xd6, 0x29, 0x7f, 0x85, 0x78, 0x33,
0xfb, 0x0e, 0x4a, 0xa8, 0xc1, 0xb4, 0xf3, 0xa9, 0xa1, 0xd9, 0x76, 0x73, 0x08, 0x8a, 0xd6, 0x38,
0xa5, 0xa6, 0x2e, 0x0c, 0x6e, 0xf9, 0xa2, 0x74, 0x2e, 0x0d, 0x36, 0x07, 0xd2, 0x84, 0xec, 0x94,
0x89, 0x07, 0x2c, 0x4a, 0x58, 0xe9, 0x95, 0x55, 0xd4, 0x20, 0x59, 0x93, 0x76, 0xc9, 0xee, 0xf0,
0x6c, 0x31, 0xcf, 0xa1, 0x33, 0x49, 0x59, 0x93, 0xea, 0x97, 0x45, 0x34, 0x3e, 0xd3, 0x68, 0xd9,
0xe6, 0x5f, 0x04, 0xdd, 0xf4, 0x87, 0xb1, 0xfe, 0x69, 0xd0, 0xc6, 0x20, 0x96, 0xae, 0x27, 0x0c,
0xa3, 0x9e, 0x7a, 0xa2, 0x91, 0xb4, 0x39, 0x90, 0xc6, 0x87, 0x0b, 0x43, 0x56, 0x8d, 0xa7, 0xad,
0x9e, 0x58, 0x9d, 0x21, 0xb5, 0x3d, 0xdc, 0x01, 0x1f, 0xe5, 0x60, 0x54, 0xd5, 0x4b, 0xf7, 0x5e,
0x9a, 0x65, 0xe1, 0x86, 0x67, 0x98, 0x48, 0xc8, 0x7b, 0x94, 0x73, 0xc0, 0xc4, 0x48, 0x96, 0x47,
0x9f, 0x3c, 0xec, 0x8b, 0xd3, 0x50, 0x83, 0x46, 0xb2, 0x49, 0xa3, 0x23, 0x81, 0xd1, 0xd4, 0xaa,
0xb6, 0x63, 0x7f, 0xc3, 0x75, 0x2a, 0xbc, 0x35, 0x98, 0x47, 0xb7, 0xed, 0x0d, 0x35, 0xe5, 0xa5,
0x70, 0xdd, 0xb6, 0xb7, 0x21, 0xa6, 0xe6, 0xa5, 0xf8, 0xf5, 0x1e, 0xaa, 0x73, 0xcd, 0x96, 0xc3,
0xe3, 0x8d, 0xfe, 0x1c, 0xd8, 0x35, 0x8c, 0x9a, 0x8f, 0x77, 0x31, 0xe8, 0x1b, 0x46, 0x94, 0x83,
0xf1, 0xd5, 0x9d, 0xe2, 0xe4, 0x4d, 0x60, 0x51, 0xb0, 0xa8, 0x8c, 0xf2, 0x18, 0xff, 0xc3, 0x60,
0x1d, 0xb0, 0x43, 0x12, 0x5f, 0xdd, 0xf9, 0x3d, 0xd0, 0x25, 0xae, 0xfd, 0x45, 0xaa, 0xe3, 0xc8,
0xa8, 0x3e, 0xfd, 0xb4, 0x3f, 0x48, 0x5d, 0x1f, 0x40, 0xe2, 0x4b, 0x5c, 0x09, 0xa8, 0xa3, 0x60,
0x2b, 0xfa, 0x81, 0x27, 0x94, 0x8d, 0xfa, 0x32, 0x7f, 0xda, 0x05, 0xed, 0x7b, 0x32, 0xf1, 0x9a,
0x32, 0xf1, 0x31, 0x3b, 0x77, 0xed, 0x7b, 0x2a, 0x35, 0x6b, 0x11, 0xdf, 0xbe, 0xd7, 0x45, 0x51,
0xe2, 0x60, 0x26, 0xd7, 0x37, 0x3c, 0xfe, 0x66, 0x4e, 0xbd, 0xda, 0xcb, 0xa1, 0x75, 0x7f, 0x37,
0x5d, 0x5a, 0x27, 0x67, 0x47, 0x41, 0x77, 0xd3, 0xa5, 0xfb, 0xe0, 0xbc, 0x31, 0x88, 0xc5, 0x17,
0xc4, 0x91, 0x60, 0x2f, 0xe5, 0xcd, 0xad, 0xa3, 0xb8, 0x8d, 0xbd, 0x73, 0x75, 0xbb, 0xd6, 0x0f,
0x22, 0x1d, 0x39, 0x87, 0x92, 0x19, 0x73, 0xea, 0x8c, 0x4d, 0xc0, 0x7b, 0x11, 0x8d, 0x40, 0xfd,
0x35, 0xc1, 0x93, 0x92, 0xc7, 0xac, 0xaa, 0x76, 0xea, 0xe9, 0x91, 0xa1, 0xaf, 0x09, 0xc0, 0x36,
0x6e, 0x8d, 0xc4, 0xd7, 0x04, 0x1d, 0x08, 0x62, 0x3f, 0x08, 0x5e, 0x7d, 0xc8, 0x67, 0x53, 0x96,
0x27, 0xe1, 0x3b, 0xf6, 0xfb, 0x3d, 0x9f, 0x8d, 0xeb, 0x9f, 0x55, 0xbc, 0x15, 0xca, 0xac, 0x1f,
0x5b, 0x77, 0xd9, 0xf1, 0x62, 0x36, 0x3d, 0xcf, 0x63, 0xf4, 0xd8, 0xda, 0xfc, 0x3e, 0xae, 0x0d,
0xc4, 0x63, 0xab, 0x05, 0xe8, 0xd7, 0xc6, 0xe6, 0xe7, 0xa3, 0x93, 0x92, 0x75, 0xde, 0xd9, 0x5b,
0x87, 0xd6, 0x44, 0xbc, 0x36, 0x22, 0x04, 0x95, 0xf2, 0xa8, 0x64, 0xcc, 0x59, 0xca, 0xda, 0xe0,
0x2d, 0x25, 0x00, 0x7a, 0xb3, 0x6d, 0x7e, 0x6e, 0x5f, 0x35, 0x1f, 0xf2, 0x38, 0xca, 0x2a, 0xc1,
0x4b, 0x7c, 0x2f, 0xd4, 0xba, 0x62, 0x88, 0xd8, 0x6c, 0x49, 0x18, 0xd5, 0xe1, 0x49, 0x9a, 0xcf,
0x9c, 0x75, 0xa8, 0x0d, 0xde, 0x3a, 0x00, 0xa0, 0x27, 0xe8, 0x01, 0x13, 0x65, 0x1a, 0x57, 0x53,
0x26, 0x9e, 0x44, 0x65, 0x34, 0x67, 0x82, 0x95, 0xf8, 0x1f, 0x5d, 0x00, 0x32, 0xb6, 0x18, 0x62,
0x82, 0x52, 0x2c, 0x08, 0xfe, 0x38, 0x78, 0xb3, 0x9e, 0xb9, 0x2c, 0x87, 0x3f, 0xea, 0x71, 0xaf,
0xf9, 0x7b, 0x37, 0xe1, 0x25, 0x15, 0x63, 0x2a, 0x4a, 0x16, 0xcd, 0x65, 0xec, 0x37, 0xd4, 0xef,
0x0d, 0xb8, 0x3d, 0xba, 0xfb, 0xee, 0xbf, 0x3f, 0x5f, 0x19, 0x7d, 0xf6, 0xf9, 0xca, 0xe8, 0xbf,
0x9f, 0xaf, 0x8c, 0x3e, 0xfd, 0x62, 0xe5, 0x95, 0xcf, 0xbe, 0x58, 0x79, 0xe5, 0x3f, 0x5f, 0xac,
0xbc, 0xf2, 0xc9, 0xab, 0xf0, 0x77, 0x77, 0x8e, 0xbf, 0xd4, 0xfc, 0xf5, 0x9c, 0x3b, 0xff, 0x0b,
0x00, 0x00, 0xff, 0xff, 0xbb, 0x6c, 0x58, 0x63, 0x9b, 0x47, 0x00, 0x00,
// 3539 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x9c, 0x5b, 0x73, 0x1c, 0x47,
0x15, 0xc7, 0xb3, 0x2f, 0x04, 0x26, 0x24, 0xc0, 0x04, 0x4c, 0x30, 0x89, 0xec, 0x38, 0xb6, 0x25,
0x59, 0xd2, 0x4a, 0xb1, 0x73, 0xe3, 0x52, 0x45, 0xad, 0x25, 0xcb, 0x56, 0xc5, 0xb2, 0x8d, 0x56,
0xb6, 0xab, 0x52, 0x45, 0x15, 0xa3, 0xd9, 0xf6, 0x6a, 0xd0, 0x68, 0x7a, 0x32, 0xd3, 0xbb, 0xb2,
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa8, 0x82, 0xe2, 0xf2, 0x04, 0x4f, 0x7c, 0x13, 0xde, 0x78,
0xcc, 0x23, 0x8f, 0x54, 0xf2, 0x45, 0xa8, 0x99, 0x3e, 0xd3, 0x97, 0x33, 0x7d, 0x7a, 0x66, 0xf3,
0xe4, 0x64, 0xcf, 0xef, 0x9c, 0x7f, 0xf7, 0xf4, 0xed, 0x74, 0xf7, 0x8c, 0x82, 0x4b, 0xf9, 0xd1,
0x66, 0x5e, 0x70, 0xc1, 0xcb, 0xcd, 0x92, 0x15, 0xf3, 0x24, 0x66, 0xcd, 0xbf, 0xc3, 0xfa, 0xe7,
0xf0, 0xc5, 0x28, 0x3b, 0x17, 0xe7, 0x39, 0xbb, 0xf8, 0x9a, 0x26, 0x63, 0x7e, 0x7a, 0x1a, 0x65,
0x93, 0x52, 0x22, 0x17, 0x2f, 0x68, 0x0b, 0x9b, 0xb3, 0x4c, 0xc0, 0xef, 0x37, 0xff, 0xfd, 0xcf,
0x41, 0xf0, 0xca, 0x76, 0x9a, 0xb0, 0x4c, 0x6c, 0x83, 0x47, 0xf8, 0x51, 0xf0, 0xf2, 0x28, 0xcf,
0xef, 0x32, 0xf1, 0x84, 0x15, 0x65, 0xc2, 0xb3, 0xf0, 0xad, 0x21, 0x08, 0x0c, 0x0f, 0xf2, 0x78,
0x38, 0xca, 0xf3, 0xa1, 0x36, 0x0e, 0x0f, 0xd8, 0xc7, 0x33, 0x56, 0x8a, 0x8b, 0x57, 0xfd, 0x50,
0x99, 0xf3, 0xac, 0x64, 0xe1, 0xb3, 0xe0, 0x6b, 0xa3, 0x3c, 0x1f, 0x33, 0xb1, 0xc3, 0xaa, 0x0a,
0x8c, 0x45, 0x24, 0x58, 0xb8, 0xdc, 0x72, 0xb5, 0x01, 0xa5, 0xb1, 0xd2, 0x0d, 0x82, 0xce, 0x61,
0xf0, 0x52, 0xa5, 0x73, 0x3c, 0x13, 0x13, 0x7e, 0x96, 0x85, 0x6f, 0xb6, 0x1d, 0xc1, 0xa4, 0x62,
0x5f, 0xf1, 0x21, 0x10, 0xf5, 0x69, 0xf0, 0xe5, 0xa7, 0x51, 0x9a, 0x32, 0xb1, 0x5d, 0xb0, 0xaa,
0xe0, 0xb6, 0x8f, 0x34, 0x0d, 0xa5, 0x4d, 0xc5, 0x7d, 0xcb, 0xcb, 0x40, 0xe0, 0x8f, 0x82, 0x97,
0xa5, 0xe5, 0x80, 0xc5, 0x7c, 0xce, 0x8a, 0xd0, 0xe9, 0x05, 0x46, 0xe2, 0x91, 0xb7, 0x20, 0x1c,
0x7b, 0x9b, 0x67, 0x73, 0x56, 0x08, 0x77, 0x6c, 0x30, 0xfa, 0x63, 0x6b, 0x08, 0x62, 0xa7, 0xc1,
0xab, 0xe6, 0x03, 0x19, 0xb3, 0xb2, 0xee, 0x30, 0xab, 0x74, 0x9d, 0x01, 0x51, 0x3a, 0x37, 0xfa,
0xa0, 0xa0, 0x96, 0x04, 0x21, 0xa8, 0xa5, 0xbc, 0x54, 0x62, 0x2b, 0xce, 0x08, 0x06, 0xa1, 0xb4,
0x56, 0x7b, 0x90, 0x20, 0xf5, 0xe3, 0xe0, 0x2b, 0x4f, 0x79, 0x71, 0x52, 0xe6, 0x51, 0xcc, 0xa0,
0xb1, 0xaf, 0xd9, 0xde, 0x8d, 0x15, 0xb7, 0xf7, 0xf5, 0x2e, 0x0c, 0x14, 0x4e, 0x82, 0x50, 0x19,
0x1f, 0x1e, 0xfd, 0x84, 0xc5, 0x62, 0x34, 0x99, 0xe0, 0x27, 0xa7, 0xbc, 0x25, 0x31, 0x1c, 0x4d,
0x26, 0xd4, 0x93, 0x73, 0xa3, 0x20, 0x76, 0x16, 0x5c, 0x40, 0x62, 0xf7, 0x93, 0xb2, 0x16, 0xdc,
0xf0, 0x47, 0x01, 0x4c, 0x89, 0x0e, 0xfb, 0xe2, 0x20, 0xfc, 0xcb, 0x41, 0xf0, 0x2d, 0x87, 0xf2,
0x01, 0x3b, 0xe5, 0x73, 0x16, 0x6e, 0x75, 0x47, 0x93, 0xa4, 0xd2, 0x7f, 0x7b, 0x01, 0x0f, 0x47,
0x53, 0x8e, 0x59, 0xca, 0x62, 0x41, 0x36, 0xa5, 0x34, 0x77, 0x36, 0xa5, 0xc2, 0x8c, 0x51, 0xd0,
0x18, 0xef, 0x32, 0xb1, 0x3d, 0x2b, 0x0a, 0x96, 0x09, 0xb2, 0x2d, 0x35, 0xd2, 0xd9, 0x96, 0x16,
0xea, 0xa8, 0xcf, 0x5d, 0x26, 0x46, 0x69, 0x4a, 0xd6, 0x47, 0x9a, 0x3b, 0xeb, 0xa3, 0x30, 0x50,
0xf8, 0x85, 0xd1, 0x66, 0x63, 0x26, 0xf6, 0xca, 0x7b, 0xc9, 0xf4, 0x38, 0x4d, 0xa6, 0xc7, 0x82,
0x4d, 0xc2, 0x4d, 0xf2, 0xa1, 0xd8, 0xa0, 0x52, 0xdd, 0xea, 0xef, 0xe0, 0xa8, 0xe1, 0x9d, 0xe7,
0x39, 0x2f, 0xe8, 0x16, 0x93, 0xe6, 0xce, 0x1a, 0x2a, 0x0c, 0x14, 0x7e, 0x14, 0xbc, 0x32, 0x8a,
0x63, 0x3e, 0xcb, 0xd4, 0x84, 0x8b, 0x96, 0x2f, 0x69, 0x6c, 0xcd, 0xb8, 0xd7, 0x3a, 0x28, 0x3d,
0xe5, 0x82, 0x0d, 0xe6, 0x8e, 0xb7, 0x9c, 0x7e, 0x68, 0xe6, 0xb8, 0xea, 0x87, 0x5a, 0xb1, 0x77,
0x58, 0xca, 0xc8, 0xd8, 0xd2, 0xd8, 0x11, 0x5b, 0x41, 0xad, 0xd8, 0x30, 0x50, 0xdc, 0xb1, 0xd1,
0x30, 0xb9, 0xea, 0x87, 0x8c, 0x15, 0x19, 0x62, 0x0b, 0x9e, 0xe3, 0x15, 0xb9, 0x71, 0x12, 0x3c,
0xa7, 0x56, 0x64, 0x1b, 0x69, 0x45, 0xdd, 0xaf, 0x26, 0x14, 0x77, 0xd4, 0x7d, 0x73, 0x06, 0xb9,
0xe2, 0x43, 0xf4, 0x80, 0x6e, 0xda, 0x8f, 0x67, 0xcf, 0x92, 0xe9, 0xe3, 0x7c, 0x52, 0xb5, 0xe2,
0xaa, 0xbb, 0x81, 0x0c, 0x84, 0x18, 0xd0, 0x04, 0x0a, 0x6a, 0x3f, 0x0c, 0x02, 0x39, 0x7d, 0x3d,
0xcc, 0x59, 0x16, 0x5e, 0xb6, 0x3c, 0x61, 0x5e, 0xab, 0x2c, 0x2a, 0xf6, 0x9b, 0x1e, 0x42, 0x3f,
0x16, 0xf9, 0x7b, 0xbd, 0xba, 0x85, 0x4e, 0x8f, 0xda, 0x44, 0x3c, 0x16, 0x84, 0xe0, 0x82, 0x8e,
0x8f, 0xf9, 0x99, 0xbb, 0xa0, 0x95, 0xc5, 0x5f, 0x50, 0x20, 0x74, 0x46, 0x05, 0x05, 0x75, 0x65,
0x54, 0x4d, 0x31, 0x7c, 0x19, 0x15, 0x66, 0x20, 0x30, 0x0f, 0xbe, 0x6e, 0x06, 0xbe, 0xcd, 0xf9,
0xc9, 0x69, 0x54, 0x9c, 0x84, 0x37, 0x68, 0xe7, 0x86, 0x51, 0x42, 0x6b, 0xbd, 0x58, 0x3d, 0x69,
0x99, 0x82, 0x63, 0x86, 0x27, 0x2d, 0xcb, 0x7f, 0xcc, 0xa8, 0x49, 0xcb, 0x81, 0xe1, 0x46, 0xbd,
0x5b, 0x44, 0xf9, 0xb1, 0xbb, 0x51, 0x6b, 0x93, 0xbf, 0x51, 0x1b, 0x04, 0xb7, 0xc0, 0x98, 0x45,
0x45, 0x7c, 0xec, 0x6e, 0x01, 0x69, 0xf3, 0xb7, 0x80, 0x62, 0x20, 0x70, 0x11, 0x7c, 0xc3, 0x0c,
0x3c, 0x9e, 0x1d, 0x95, 0x71, 0x91, 0x1c, 0xb1, 0x70, 0x8d, 0xf6, 0x56, 0x90, 0x92, 0x5a, 0xef,
0x07, 0xeb, 0x0c, 0x11, 0x34, 0x1b, 0xdb, 0xde, 0xa4, 0x44, 0x19, 0x62, 0x13, 0xc3, 0x20, 0x88,
0x0c, 0xd1, 0x4d, 0xe2, 0xea, 0xdd, 0x2d, 0xf8, 0x2c, 0x2f, 0x3b, 0xaa, 0x87, 0x20, 0x7f, 0xf5,
0xda, 0x30, 0x68, 0x3e, 0x0f, 0xbe, 0x69, 0x3e, 0xd2, 0xc7, 0x59, 0xa9, 0x54, 0x37, 0xe8, 0xe7,
0x64, 0x60, 0x44, 0x1e, 0xe7, 0xc1, 0x41, 0x39, 0x0e, 0xbe, 0xda, 0x28, 0x8b, 0x1d, 0x26, 0xa2,
0x24, 0x2d, 0xc3, 0xeb, 0xee, 0x18, 0x8d, 0x5d, 0x69, 0x2d, 0x77, 0x72, 0x78, 0x08, 0xed, 0xcc,
0xf2, 0x34, 0x89, 0xdb, 0x49, 0x37, 0xf8, 0x2a, 0xb3, 0x7f, 0x08, 0x99, 0x98, 0x9e, 0xd8, 0x55,
0x35, 0xe4, 0x7f, 0x1c, 0x9e, 0xe7, 0x78, 0x62, 0xd7, 0x25, 0xd4, 0x08, 0x31, 0xb1, 0x13, 0x28,
0xae, 0xcf, 0x98, 0x89, 0xfb, 0xd1, 0x39, 0x9f, 0x11, 0x53, 0x82, 0x32, 0xfb, 0xeb, 0x63, 0x62,
0xa0, 0x30, 0x0b, 0x2e, 0x28, 0x85, 0xbd, 0x4c, 0xb0, 0x22, 0x8b, 0xd2, 0xdd, 0x34, 0x9a, 0x96,
0x21, 0x31, 0x6e, 0x6c, 0x4a, 0xe9, 0x6d, 0xf4, 0xa4, 0x1d, 0x8f, 0x71, 0xaf, 0xdc, 0x8d, 0xe6,
0xbc, 0x48, 0x04, 0xfd, 0x18, 0x35, 0xd2, 0xf9, 0x18, 0x2d, 0xd4, 0xa9, 0x36, 0x2a, 0xe2, 0xe3,
0x64, 0xce, 0x26, 0x1e, 0xb5, 0x06, 0xe9, 0xa1, 0x66, 0xa0, 0x8e, 0x46, 0x1b, 0xf3, 0x59, 0x11,
0x33, 0xb2, 0xd1, 0xa4, 0xb9, 0xb3, 0xd1, 0x14, 0x86, 0xeb, 0x53, 0xed, 0x56, 0x74, 0x57, 0x77,
0xd6, 0xc7, 0x42, 0xfc, 0xf5, 0xc1, 0x28, 0x1e, 0xb9, 0xb5, 0x5d, 0xa6, 0x8c, 0xd7, 0x49, 0x7f,
0x3b, 0x6b, 0x5c, 0xee, 0xe4, 0xf0, 0xc4, 0x54, 0x19, 0xed, 0x66, 0xda, 0xa0, 0x62, 0xb8, 0x9b,
0x6a, 0xd8, 0x17, 0x27, 0x95, 0x55, 0x77, 0xf4, 0x2b, 0xb7, 0xba, 0xe4, 0xb0, 0x2f, 0x8e, 0x9b,
0x71, 0x94, 0xe7, 0xe9, 0xf9, 0x21, 0x3b, 0xcd, 0x53, 0xb2, 0x19, 0x2d, 0xc4, 0xdf, 0x8c, 0x18,
0xc5, 0x8b, 0xff, 0x21, 0xaf, 0x52, 0x0b, 0xe7, 0xe2, 0x5f, 0x9b, 0xfc, 0x8b, 0x7f, 0x83, 0xe0,
0x45, 0x6c, 0x34, 0x99, 0x3c, 0x4d, 0xc4, 0xb1, 0xfc, 0x9f, 0xbd, 0x89, 0x7b, 0x11, 0x43, 0x90,
0x7f, 0x11, 0x6b, 0xc3, 0xfa, 0x08, 0xb0, 0xc9, 0x22, 0xa3, 0x82, 0xdd, 0x3e, 0xbf, 0x9f, 0x64,
0x27, 0xa1, 0x7b, 0x8d, 0xd0, 0x00, 0x71, 0x04, 0xe8, 0x04, 0x71, 0xdd, 0xaa, 0xd4, 0xf8, 0x76,
0xc1, 0xa2, 0x49, 0x5c, 0xcc, 0x4e, 0x8f, 0x4a, 0x77, 0xdd, 0x10, 0xe4, 0xaf, 0x5b, 0x1b, 0xc6,
0x59, 0xe7, 0x98, 0x09, 0x53, 0x92, 0x9a, 0x80, 0x5c, 0x8a, 0x6b, 0xbd, 0x58, 0x9c, 0x92, 0x3f,
0xce, 0x26, 0xdc, 0x9d, 0x92, 0x57, 0x16, 0x7f, 0x4a, 0x0e, 0x04, 0x0e, 0x79, 0xc0, 0xa8, 0x90,
0x95, 0xc5, 0x1f, 0x12, 0x08, 0xd7, 0x1c, 0x04, 0x3b, 0x7a, 0x72, 0x0e, 0x42, 0x5b, 0xfa, 0xe5,
0x4e, 0x0e, 0x8f, 0xc7, 0x26, 0x37, 0xdf, 0x65, 0x22, 0x3e, 0x76, 0x8f, 0x47, 0x0b, 0xf1, 0x8f,
0x47, 0x8c, 0xe2, 0x2a, 0x1d, 0x72, 0xb5, 0xb7, 0xb8, 0xee, 0x1e, 0x71, 0xad, 0x7d, 0xc5, 0x72,
0x27, 0x87, 0x73, 0xf3, 0xbd, 0xd3, 0xfa, 0x99, 0x39, 0x87, 0xb4, 0xb4, 0xf9, 0x73, 0x73, 0xc5,
0xe0, 0xd2, 0x4b, 0x43, 0xf5, 0x38, 0xdd, 0xa5, 0xd7, 0x76, 0x7f, 0xe9, 0x2d, 0x0e, 0x44, 0xfe,
0x36, 0x08, 0x2e, 0x99, 0x2a, 0x0f, 0xb8, 0x48, 0x78, 0xf6, 0x24, 0x4a, 0x93, 0x6a, 0xff, 0x7b,
0xc8, 0x4f, 0x58, 0x16, 0xbe, 0xef, 0x29, 0xad, 0xe4, 0x87, 0x96, 0x83, 0x2a, 0xc5, 0x07, 0x8b,
0x3b, 0xba, 0x77, 0x86, 0x07, 0x2c, 0x8d, 0x2a, 0xdc, 0xb7, 0x33, 0x6c, 0x98, 0x3e, 0x3b, 0x43,
0x83, 0x05, 0xc1, 0x5f, 0x0d, 0x82, 0x8b, 0x2e, 0xc5, 0x87, 0x79, 0xad, 0xbb, 0xd5, 0x1d, 0x4b,
0x92, 0xc4, 0x21, 0xa8, 0xdf, 0x03, 0xca, 0xf0, 0xb3, 0xe0, 0xb5, 0xc6, 0xa4, 0xcf, 0x48, 0xa1,
0x00, 0xf6, 0xc2, 0xa7, 0xca, 0x8f, 0x39, 0x25, 0xbf, 0xd9, 0x9b, 0xd7, 0x29, 0x95, 0x5d, 0xae,
0x12, 0xa5, 0x54, 0x2a, 0x06, 0x98, 0x89, 0x94, 0xca, 0x81, 0xe1, 0x35, 0xa5, 0x41, 0x46, 0x93,
0x89, 0x73, 0x4d, 0x51, 0x21, 0xcc, 0x43, 0xed, 0x95, 0x6e, 0x10, 0xf7, 0x9d, 0xc6, 0x0c, 0x09,
0xd5, 0x0d, 0x5f, 0x04, 0x94, 0x54, 0xad, 0xf5, 0x62, 0xf5, 0x51, 0x6c, 0xab, 0x62, 0xbb, 0x2c,
0x12, 0xb3, 0xa2, 0x75, 0x14, 0xdb, 0x2e, 0x77, 0x03, 0x12, 0x47, 0xb1, 0x5e, 0x07, 0xd0, 0xff,
0xdd, 0x20, 0x78, 0xdd, 0xe6, 0x64, 0x13, 0xab, 0x32, 0xdc, 0xf4, 0x85, 0xb4, 0x59, 0x55, 0x8c,
0x5b, 0x0b, 0xf9, 0x40, 0x49, 0x7e, 0x33, 0x08, 0xbe, 0x6d, 0xa3, 0xf5, 0x65, 0xc3, 0x3c, 0x4a,
0xd2, 0xe8, 0x28, 0x65, 0xe1, 0xdb, 0xbe, 0xa0, 0x16, 0xaa, 0xca, 0x71, 0x73, 0x11, 0x17, 0xbc,
0xe3, 0x92, 0xe3, 0xcd, 0xd8, 0x44, 0xae, 0xd3, 0xa3, 0xd2, 0xb1, 0x8f, 0xdc, 0xe8, 0x49, 0xeb,
0x0b, 0x1c, 0xfd, 0xb3, 0xf9, 0x00, 0x9c, 0x59, 0x2e, 0xf8, 0x1a, 0x35, 0xf1, 0x66, 0xb9, 0x4e,
0x1c, 0x84, 0x45, 0x93, 0x45, 0x99, 0xc2, 0xd5, 0xe8, 0x5a, 0xef, 0x0c, 0x64, 0x0e, 0xb1, 0x8d,
0x9e, 0x34, 0xa8, 0xfe, 0x3c, 0x78, 0xad, 0xad, 0x0a, 0x97, 0x46, 0x9b, 0x9d, 0xa1, 0xd0, 0x9d,
0xd1, 0x56, 0x7f, 0x07, 0x7d, 0x8c, 0x74, 0x2f, 0x29, 0x05, 0x2f, 0xce, 0xc7, 0xc7, 0xfc, 0xac,
0xb9, 0x06, 0xb7, 0xa7, 0x09, 0x00, 0x86, 0x06, 0x41, 0x1c, 0x23, 0xb9, 0xc9, 0x96, 0x94, 0xbe,
0x2e, 0x2f, 0x09, 0x29, 0x83, 0xe8, 0x90, 0xb2, 0x49, 0x3d, 0x49, 0x36, 0xb5, 0xd2, 0x77, 0xfb,
0xcb, 0xee, 0xa2, 0xb6, 0xef, 0xf7, 0x57, 0xba, 0x41, 0xbd, 0x55, 0xd9, 0x4d, 0x52, 0xf6, 0xf0,
0xd9, 0xb3, 0x94, 0x47, 0x13, 0xb4, 0x55, 0xa9, 0x2c, 0x43, 0x30, 0x11, 0x5b, 0x15, 0x84, 0xe8,
0x45, 0xa4, 0x32, 0x54, 0xbd, 0xb3, 0x89, 0x7c, 0xad, 0xed, 0x66, 0x98, 0x89, 0x45, 0xc4, 0x81,
0xe9, 0xc4, 0xb7, 0x32, 0x3e, 0xce, 0xeb, 0xe0, 0x97, 0xdb, 0x5e, 0xd2, 0x42, 0x24, 0xbe, 0x36,
0xa1, 0x13, 0xb8, 0xea, 0xf7, 0x1d, 0x7e, 0x96, 0xd5, 0x41, 0x1d, 0x15, 0x6d, 0x6c, 0x44, 0x02,
0x87, 0x19, 0x08, 0xfc, 0x61, 0xf0, 0xc5, 0x3a, 0x70, 0xc1, 0xf3, 0x70, 0xc9, 0xe1, 0x50, 0x18,
0xf7, 0x28, 0x97, 0x48, 0xbb, 0xde, 0x29, 0x3d, 0x88, 0xe6, 0xc9, 0x54, 0x4d, 0x2a, 0x72, 0x8c,
0xe0, 0x9d, 0x92, 0x66, 0x86, 0x06, 0x44, 0xec, 0x94, 0x48, 0x18, 0x34, 0xff, 0x3a, 0x08, 0x2e,
0x6b, 0xe6, 0x6e, 0x73, 0x80, 0xb6, 0x97, 0x3d, 0xe3, 0xd5, 0xb6, 0xb1, 0xda, 0xca, 0x95, 0xe1,
0x7b, 0x54, 0x48, 0x37, 0xaf, 0x8a, 0xf2, 0xfe, 0xc2, 0x7e, 0x3a, 0x4d, 0x6a, 0xb6, 0xde, 0x72,
0x2e, 0xde, 0x2d, 0xf8, 0xa9, 0xf4, 0x40, 0x69, 0x92, 0xda, 0xa1, 0x63, 0x8e, 0x48, 0x93, 0x7c,
0xbc, 0xb1, 0xd6, 0x52, 0xea, 0xf5, 0x0a, 0x73, 0xb3, 0x5f, 0x44, 0x6b, 0x9d, 0xb9, 0xb5, 0x90,
0x8f, 0xbe, 0x07, 0x54, 0x05, 0x49, 0x79, 0x86, 0xef, 0x18, 0x75, 0x94, 0xca, 0x48, 0xdc, 0x03,
0xb6, 0x20, 0x3d, 0x0b, 0x35, 0x26, 0xb9, 0x83, 0x1b, 0xa5, 0x29, 0x9a, 0x85, 0x94, 0xab, 0x02,
0x88, 0x59, 0xc8, 0x09, 0x82, 0xce, 0x41, 0xf0, 0x52, 0xd5, 0xb8, 0x8f, 0x0a, 0x36, 0x4f, 0x18,
0xbe, 0xad, 0x32, 0x2c, 0xc4, 0x70, 0xb6, 0x09, 0x7d, 0x6d, 0xfc, 0x38, 0x2b, 0xf3, 0x34, 0x2a,
0x8f, 0xe1, 0xb6, 0xc4, 0xae, 0x73, 0x63, 0xc4, 0xf7, 0x25, 0xd7, 0x3a, 0x28, 0xbd, 0x2b, 0x6b,
0x6c, 0x6a, 0xc6, 0xb8, 0xee, 0x76, 0x6d, 0xcd, 0x1a, 0xcb, 0x9d, 0x9c, 0x9e, 0x9d, 0x6f, 0xa7,
0x3c, 0x3e, 0x81, 0x69, 0xce, 0xae, 0x75, 0x6d, 0xc1, 0xf3, 0xdc, 0x15, 0x1f, 0xa2, 0x27, 0xba,
0xda, 0x70, 0xc0, 0xf2, 0x34, 0x8a, 0xf1, 0x3d, 0x9e, 0xf4, 0x01, 0x1b, 0x31, 0xd1, 0x61, 0x06,
0x15, 0x17, 0xee, 0x07, 0x5d, 0xc5, 0x45, 0xd7, 0x83, 0x57, 0x7c, 0x88, 0x9e, 0xea, 0x6b, 0xc3,
0x38, 0x4f, 0x13, 0x81, 0xfa, 0x86, 0xf4, 0xa8, 0x2d, 0x44, 0xdf, 0xb0, 0x09, 0x14, 0x72, 0x9f,
0x15, 0x53, 0xe6, 0x0c, 0x59, 0x5b, 0xbc, 0x21, 0x1b, 0x02, 0x42, 0x3e, 0x08, 0xbe, 0x24, 0xeb,
0xce, 0xf3, 0xf3, 0xf0, 0x92, 0xab, 0x5a, 0x3c, 0x3f, 0x57, 0x01, 0x2f, 0xd3, 0x00, 0x2a, 0xe2,
0xa3, 0xa8, 0x14, 0xee, 0x22, 0xd6, 0x16, 0x6f, 0x11, 0x1b, 0x42, 0xaf, 0x43, 0xb2, 0x88, 0x33,
0x81, 0xd6, 0x21, 0x28, 0x80, 0x71, 0xa9, 0x71, 0x89, 0xb4, 0xeb, 0xe1, 0x25, 0x5b, 0x85, 0x89,
0xdd, 0x84, 0xa5, 0x93, 0x12, 0x0d, 0x2f, 0x78, 0xee, 0x8d, 0x95, 0x18, 0x5e, 0x6d, 0x0a, 0x75,
0x25, 0x38, 0x80, 0x72, 0xd5, 0x0e, 0x9d, 0x3d, 0x5d, 0xf1, 0x21, 0x3a, 0x2f, 0xa9, 0x0d, 0xc6,
0xf1, 0xba, 0xab, 0x3c, 0x8e, 0xd3, 0xf5, 0xeb, 0x5d, 0x18, 0x28, 0xfc, 0x61, 0x10, 0xbc, 0xa1,
0x24, 0xf6, 0xf9, 0x9c, 0x1d, 0xf2, 0x3b, 0xcf, 0x93, 0x52, 0x24, 0xd9, 0x14, 0x96, 0xa6, 0x5b,
0x44, 0x24, 0x17, 0xac, 0xe4, 0xdf, 0x59, 0xcc, 0x49, 0xaf, 0x90, 0xa8, 0x2c, 0x0f, 0xd8, 0x99,
0x73, 0x85, 0xc4, 0x11, 0x15, 0x47, 0xac, 0x90, 0x3e, 0x5e, 0xef, 0x86, 0x95, 0x38, 0xbc, 0x8b,
0x78, 0xc8, 0x9b, 0x64, 0x85, 0x8a, 0x86, 0x41, 0x62, 0x5f, 0xe0, 0x75, 0xd0, 0xc9, 0xba, 0xd2,
0xd7, 0x9d, 0x74, 0x85, 0x88, 0xd3, 0xee, 0xa8, 0xab, 0x3d, 0x48, 0x87, 0x94, 0xbe, 0x23, 0xa2,
0xa4, 0xda, 0x57, 0x44, 0xab, 0x3d, 0x48, 0x63, 0x67, 0x6d, 0x56, 0xeb, 0x76, 0x14, 0x9f, 0x4c,
0x0b, 0x3e, 0xcb, 0x26, 0xdb, 0x3c, 0xe5, 0x05, 0xda, 0x59, 0x5b, 0xa5, 0x46, 0x28, 0xb1, 0xb3,
0xee, 0x70, 0xd1, 0x89, 0x81, 0x59, 0x8a, 0x51, 0x9a, 0x4c, 0xf1, 0xf6, 0xc4, 0x0a, 0x54, 0x03,
0x44, 0x62, 0xe0, 0x04, 0x1d, 0x9d, 0x48, 0x6e, 0x5f, 0x44, 0x12, 0x47, 0xa9, 0xd4, 0xdb, 0xa4,
0xc3, 0x58, 0x60, 0x67, 0x27, 0x72, 0x38, 0x38, 0xea, 0x79, 0x38, 0x2b, 0xb2, 0xbd, 0x4c, 0x70,
0xb2, 0x9e, 0x0d, 0xd0, 0x59, 0x4f, 0x03, 0xd4, 0xd9, 0x44, 0x6d, 0x3e, 0x64, 0xcf, 0xab, 0xd2,
0x54, 0xff, 0x84, 0x8e, 0x29, 0xa7, 0xfa, 0x7d, 0x08, 0x76, 0x22, 0x9b, 0x70, 0x71, 0xa8, 0x32,
0x20, 0x22, 0x3b, 0x8c, 0xc7, 0xdb, 0xee, 0x26, 0x2b, 0xdd, 0xa0, 0x5b, 0x67, 0x2c, 0xce, 0x53,
0xe6, 0xd3, 0xa9, 0x81, 0x3e, 0x3a, 0x0d, 0xa8, 0x2f, 0x11, 0xac, 0xfa, 0x1c, 0xb3, 0xf8, 0xa4,
0x75, 0xd7, 0x6c, 0x17, 0x54, 0x22, 0xc4, 0x25, 0x02, 0x81, 0xba, 0x9b, 0x68, 0x2f, 0xe6, 0x99,
0xaf, 0x89, 0x2a, 0x7b, 0x9f, 0x26, 0x02, 0x4e, 0xef, 0xee, 0x94, 0x15, 0x7a, 0xa6, 0x6c, 0xa6,
0x35, 0x22, 0x82, 0x09, 0x11, 0xbb, 0x3b, 0x12, 0xd6, 0xe7, 0xa4, 0x58, 0x73, 0xbf, 0xfd, 0xf6,
0x55, 0x2b, 0xca, 0x3e, 0xfd, 0xf6, 0x15, 0xc5, 0xd2, 0x95, 0x94, 0x7d, 0xa4, 0x23, 0x8a, 0xdd,
0x4f, 0xd6, 0xfb, 0xc1, 0xfa, 0xea, 0xd9, 0xd2, 0xdc, 0x4e, 0x59, 0x54, 0x48, 0xd5, 0x0d, 0x4f,
0x20, 0x8d, 0x11, 0x87, 0x72, 0x1e, 0x1c, 0x4d, 0x61, 0x96, 0xf2, 0x36, 0xcf, 0x04, 0xcb, 0x84,
0x6b, 0x0a, 0xb3, 0x83, 0x01, 0xe8, 0x9b, 0xc2, 0x28, 0x07, 0xd4, 0x6f, 0x77, 0x93, 0x94, 0x8d,
0x99, 0x78, 0x10, 0x9d, 0x32, 0x57, 0xbf, 0xad, 0x8f, 0x1a, 0xc0, 0xee, 0xeb, 0xb7, 0x88, 0x43,
0x43, 0x7e, 0xef, 0x34, 0x9a, 0x2a, 0x15, 0x87, 0x77, 0x6d, 0x6f, 0xc9, 0xac, 0x74, 0x83, 0x48,
0xe7, 0x49, 0x32, 0x61, 0xdc, 0xa3, 0x53, 0xdb, 0xfb, 0xe8, 0x60, 0x10, 0x65, 0x4e, 0x55, 0x6d,
0xe5, 0x7e, 0x64, 0x94, 0x4d, 0x60, 0x17, 0x36, 0x24, 0x1e, 0x0a, 0xe2, 0x7c, 0x99, 0x13, 0xc1,
0xa3, 0xf1, 0xd1, 0x1c, 0xa1, 0xf9, 0xc6, 0x87, 0x3a, 0x21, 0xeb, 0x33, 0x3e, 0x5c, 0x30, 0x68,
0xfe, 0x14, 0xc6, 0xc7, 0x4e, 0x24, 0xa2, 0x6a, 0x1f, 0xfd, 0x24, 0x61, 0x67, 0xb0, 0x8d, 0x73,
0xd4, 0xb7, 0xa1, 0x86, 0x15, 0x86, 0xf7, 0x74, 0x9b, 0xbd, 0x79, 0x8f, 0x36, 0x64, 0xe7, 0x9d,
0xda, 0x28, 0x4d, 0xdf, 0xec, 0xcd, 0x7b, 0xb4, 0xe1, 0x0d, 0xe2, 0x4e, 0x6d, 0xf4, 0x1a, 0xf1,
0x66, 0x6f, 0x1e, 0xb4, 0x7f, 0x3d, 0x08, 0x2e, 0xb6, 0xc4, 0xab, 0x1c, 0x28, 0x16, 0xc9, 0x9c,
0xb9, 0x52, 0x39, 0x3b, 0x9e, 0x42, 0x7d, 0xa9, 0x1c, 0xed, 0x02, 0xa5, 0xf8, 0xfd, 0x20, 0x78,
0xdd, 0x55, 0x8a, 0x47, 0xbc, 0x4c, 0xea, 0x2b, 0xc7, 0x5b, 0x3d, 0x82, 0x36, 0xb0, 0x6f, 0xc3,
0xe2, 0x73, 0xd2, 0x17, 0x36, 0x16, 0xaa, 0x5f, 0xeb, 0x5a, 0xf7, 0xc4, 0x6b, 0xbf, 0xdd, 0xb5,
0xd1, 0x93, 0xd6, 0x37, 0x18, 0x16, 0x63, 0x5e, 0x9d, 0xf8, 0x5a, 0xd5, 0x79, 0x7b, 0xb2, 0xd5,
0xdf, 0x01, 0xe4, 0x7f, 0xdb, 0xe4, 0xf4, 0x58, 0x1f, 0x06, 0xc1, 0xcd, 0x3e, 0x11, 0xd1, 0x40,
0xb8, 0xb5, 0x90, 0x0f, 0x14, 0xe4, 0x1f, 0x83, 0xe0, 0x8a, 0xb3, 0x20, 0xf6, 0xed, 0xdd, 0x77,
0xfa, 0xc4, 0x76, 0xdf, 0xe2, 0x7d, 0xf7, 0xf3, 0xb8, 0x42, 0xe9, 0xfe, 0xd8, 0x6c, 0xad, 0x1b,
0x8f, 0xfa, 0xd5, 0xdb, 0x87, 0xc5, 0x84, 0x15, 0x30, 0x62, 0x7d, 0x9d, 0x4e, 0xc3, 0x78, 0xdc,
0xbe, 0xbb, 0xa0, 0x17, 0x14, 0xe7, 0x4f, 0x83, 0x60, 0xc9, 0x82, 0xe1, 0x05, 0x26, 0xa3, 0x3c,
0xbe, 0xc8, 0x06, 0x8d, 0x0b, 0xf4, 0xde, 0xa2, 0x6e, 0x50, 0xa2, 0x7f, 0x0d, 0x82, 0x6b, 0x16,
0xad, 0x0f, 0x8e, 0xd1, 0x19, 0xc4, 0xf7, 0x3c, 0x0a, 0x94, 0x93, 0x2a, 0xde, 0xf7, 0x3f, 0x9f,
0xb3, 0xbe, 0x1c, 0xb5, 0x5c, 0x76, 0x93, 0x54, 0xb0, 0xa2, 0xfd, 0x75, 0x9b, 0x1d, 0x57, 0x52,
0x43, 0xfa, 0xeb, 0x36, 0x0f, 0x6e, 0x7c, 0xdd, 0xe6, 0x50, 0x76, 0x7e, 0xdd, 0xe6, 0x8c, 0xe6,
0xfd, 0xba, 0xcd, 0xef, 0x41, 0x4d, 0xf8, 0x4d, 0x11, 0xe4, 0x39, 0x6c, 0xaf, 0x88, 0xf6, 0xb1,
0xec, 0xcd, 0x45, 0x5c, 0x88, 0x25, 0x4f, 0x72, 0x63, 0x5e, 0x88, 0xb0, 0xc7, 0x33, 0x1d, 0x9b,
0x67, 0x6e, 0x9b, 0xbd, 0x79, 0xd0, 0xfe, 0x18, 0xf6, 0x1a, 0x6a, 0x82, 0xe7, 0x45, 0xfd, 0x65,
0xe3, 0x9a, 0x6f, 0xc2, 0xae, 0x22, 0x98, 0x2d, 0xbf, 0xde, 0x0f, 0x26, 0xaa, 0x5b, 0x11, 0xd0,
0xe8, 0xc3, 0xae, 0x40, 0xa8, 0xc9, 0x37, 0x7b, 0xf3, 0xc4, 0xc2, 0x22, 0xb5, 0x65, 0x6b, 0xf7,
0x08, 0x66, 0xb7, 0xf5, 0x56, 0x7f, 0x07, 0xfd, 0x3e, 0x40, 0x4b, 0xbe, 0x6e, 0xe7, 0xce, 0x27,
0x68, 0xb5, 0xf2, 0x46, 0x4f, 0xda, 0x97, 0x50, 0x98, 0x4b, 0x6a, 0x57, 0x42, 0xe1, 0x5c, 0x56,
0xdf, 0x59, 0xcc, 0x09, 0xca, 0xf2, 0x97, 0x41, 0x70, 0x89, 0x2c, 0x0b, 0xf4, 0x82, 0xf7, 0xfa,
0x46, 0x46, 0xbd, 0xe1, 0xfd, 0x85, 0xfd, 0xa0, 0x50, 0x7f, 0x1f, 0x04, 0x97, 0x3d, 0x85, 0x92,
0xdd, 0x63, 0x81, 0xe8, 0x76, 0x37, 0xf9, 0x60, 0x71, 0x47, 0x6a, 0x81, 0x35, 0xf1, 0xba, 0xdf,
0xf4, 0x6e, 0x04, 0xab, 0xff, 0xbc, 0xbb, 0xa0, 0x17, 0x3e, 0x70, 0xa9, 0xd2, 0x00, 0xd8, 0x8b,
0xb8, 0x0e, 0x5c, 0xea, 0x2c, 0x01, 0xed, 0x41, 0x96, 0x3b, 0x39, 0x97, 0xc8, 0x9d, 0xe7, 0x79,
0x94, 0x4d, 0x68, 0x11, 0x69, 0xef, 0x16, 0x51, 0x1c, 0x3e, 0xa8, 0xaa, 0xac, 0x07, 0xbc, 0xd9,
0x58, 0xad, 0x52, 0xfe, 0x0a, 0xf1, 0x1e, 0x54, 0xb5, 0x50, 0x42, 0x0d, 0xb2, 0x48, 0x9f, 0x1a,
0x4a, 0x1e, 0x6f, 0xf4, 0x41, 0x51, 0xca, 0xae, 0xd4, 0xd4, 0xf9, 0xf7, 0xba, 0x2f, 0x4a, 0xeb,
0x0c, 0x7c, 0xa3, 0x27, 0x4d, 0xc8, 0x8e, 0x99, 0xb8, 0xc7, 0xa2, 0x09, 0x2b, 0xbc, 0xb2, 0x8a,
0xea, 0x25, 0x6b, 0xd2, 0x2e, 0xd9, 0x6d, 0x9e, 0xce, 0x4e, 0x33, 0x68, 0x4c, 0x52, 0xd6, 0xa4,
0xba, 0x65, 0x11, 0x8d, 0x8f, 0xe8, 0xb4, 0x6c, 0xfd, 0x09, 0xed, 0x0d, 0x7f, 0x18, 0xeb, 0x5b,
0xda, 0xb5, 0x5e, 0x2c, 0x5d, 0x4f, 0xe8, 0x46, 0x1d, 0xf5, 0x44, 0x3d, 0x69, 0xa3, 0x27, 0x8d,
0xcf, 0xca, 0x0c, 0x59, 0xd5, 0x9f, 0x36, 0x3b, 0x62, 0xb5, 0xba, 0xd4, 0x56, 0x7f, 0x07, 0x7c,
0x32, 0x09, 0xbd, 0xaa, 0xda, 0x89, 0xec, 0x26, 0x69, 0x1a, 0xae, 0x79, 0xba, 0x49, 0x03, 0x79,
0x4f, 0x26, 0x1d, 0x30, 0xd1, 0x93, 0x9b, 0x93, 0xbc, 0x2c, 0xec, 0x8a, 0x53, 0x53, 0xbd, 0x7a,
0xb2, 0x49, 0xa3, 0x13, 0x2e, 0xe3, 0x51, 0xab, 0xda, 0x0e, 0xfd, 0x0f, 0xae, 0x55, 0xe1, 0xcd,
0xde, 0x3c, 0xba, 0x3c, 0xae, 0xa9, 0x7a, 0x65, 0xb9, 0x4a, 0x85, 0xb0, 0x56, 0x92, 0x6b, 0x1d,
0x54, 0xeb, 0xd6, 0x28, 0x83, 0x77, 0x11, 0xf4, 0xd7, 0x2d, 0xae, 0x6e, 0x54, 0x7f, 0x8b, 0x82,
0x41, 0x5f, 0x37, 0xa2, 0x1c, 0x8c, 0x97, 0xc8, 0x15, 0xd7, 0x5c, 0x6c, 0xe5, 0x39, 0x8b, 0x8a,
0x28, 0x8b, 0x9d, 0x7b, 0x8d, 0x3a, 0x60, 0x8b, 0xf4, 0xed, 0x35, 0x48, 0x0f, 0x74, 0x27, 0x69,
0x7f, 0x60, 0xe1, 0x38, 0x01, 0x55, 0x5f, 0x32, 0xd8, 0xdf, 0x57, 0xac, 0xf6, 0x20, 0xf1, 0x9d,
0x64, 0x03, 0xa8, 0x93, 0x4d, 0x29, 0xfa, 0xb6, 0x27, 0x94, 0x8d, 0xfa, 0xf6, 0x35, 0xb4, 0x0b,
0x5a, 0xf7, 0x54, 0xc6, 0xc2, 0xc4, 0x87, 0xec, 0xdc, 0xb5, 0xee, 0xe9, 0x84, 0xa3, 0x46, 0x7c,
0xeb, 0x5e, 0x1b, 0x45, 0x89, 0x83, 0x99, 0xd8, 0x5e, 0xf7, 0xf8, 0x9b, 0xb9, 0xec, 0x72, 0x27,
0x87, 0xe6, 0xfd, 0x9d, 0x64, 0x6e, 0x1d, 0x04, 0x3b, 0x0a, 0xba, 0x93, 0xcc, 0xdd, 0xe7, 0xc0,
0x6b, 0xbd, 0x58, 0x7c, 0xdf, 0x19, 0x09, 0xf6, 0xbc, 0xb9, 0x88, 0x74, 0x14, 0xb7, 0xb6, 0xb7,
0x6e, 0x22, 0x57, 0xba, 0x41, 0xa4, 0xd3, 0x8c, 0xa1, 0xc9, 0x94, 0x39, 0x75, 0x86, 0x26, 0xe0,
0xbd, 0x57, 0x45, 0xa0, 0x7e, 0x39, 0xee, 0x51, 0xc1, 0x63, 0x56, 0x96, 0xdb, 0xd5, 0xf0, 0x48,
0xd1, 0xcb, 0x71, 0x60, 0x1b, 0x4a, 0x23, 0xf1, 0x72, 0x5c, 0x0b, 0x82, 0xd8, 0xf7, 0x82, 0x17,
0xef, 0xf3, 0xe9, 0x98, 0x65, 0x93, 0xf0, 0x0d, 0xfb, 0x75, 0x34, 0x3e, 0x1d, 0x56, 0x3f, 0xab,
0x78, 0x4b, 0x94, 0x59, 0xbf, 0x3b, 0xb4, 0xc3, 0x8e, 0x66, 0xd3, 0xf1, 0x79, 0x16, 0xa3, 0x77,
0x87, 0xea, 0xdf, 0x87, 0x95, 0x81, 0x78, 0x77, 0xc8, 0x02, 0xf4, 0xcb, 0x33, 0xf5, 0xcf, 0x87,
0xc7, 0x05, 0x6b, 0xbd, 0x36, 0x26, 0x1d, 0xa4, 0x89, 0x78, 0x79, 0x06, 0x21, 0xa8, 0x94, 0x87,
0x05, 0x63, 0xce, 0x52, 0x56, 0x06, 0x6f, 0x29, 0x01, 0xd0, 0x8b, 0x6d, 0xfd, 0xb3, 0x7c, 0x49,
0xe7, 0x3e, 0x8f, 0xa3, 0xb4, 0x14, 0xbc, 0xc0, 0xd7, 0x1c, 0xd2, 0x15, 0x43, 0xc4, 0x62, 0x4b,
0xc2, 0xa8, 0x0e, 0x8f, 0x92, 0x6c, 0xea, 0xac, 0x43, 0x65, 0xf0, 0xd6, 0x01, 0x00, 0x3d, 0x40,
0xf7, 0x99, 0x28, 0x92, 0xb8, 0x1c, 0x33, 0xf1, 0x28, 0x2a, 0xa2, 0x53, 0x26, 0x58, 0x81, 0xbf,
0x21, 0x04, 0x64, 0x68, 0x31, 0xc4, 0x00, 0xa5, 0x58, 0x10, 0xfc, 0x41, 0xf0, 0x6a, 0x35, 0x72,
0x59, 0x06, 0x7f, 0x05, 0xeb, 0x4e, 0xfd, 0x07, 0xe2, 0xc2, 0x0b, 0x2a, 0xc6, 0x58, 0x14, 0x2c,
0x3a, 0x6d, 0x62, 0xbf, 0xa2, 0x7e, 0xaf, 0xc1, 0xad, 0xc1, 0xed, 0x37, 0xff, 0xf3, 0xe9, 0xd2,
0xe0, 0x93, 0x4f, 0x97, 0x06, 0xff, 0xfb, 0x74, 0x69, 0xf0, 0xe7, 0xcf, 0x96, 0x5e, 0xf8, 0xe4,
0xb3, 0xa5, 0x17, 0xfe, 0xfb, 0xd9, 0xd2, 0x0b, 0x1f, 0xbd, 0x08, 0x7f, 0xa8, 0xee, 0xe8, 0x0b,
0xf5, 0x9f, 0x9b, 0xbb, 0xf5, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x91, 0x3a, 0xee, 0x27, 0xcc,
0x4e, 0x00, 0x00,
}
// This is a compile-time assertion to ensure that this generated file
@ -295,6 +311,7 @@ type ClientCommandsHandler interface {
ObjectSetInternalFlags(context.Context, *pb.RpcObjectSetInternalFlagsRequest) *pb.RpcObjectSetInternalFlagsResponse
ObjectSetIsFavorite(context.Context, *pb.RpcObjectSetIsFavoriteRequest) *pb.RpcObjectSetIsFavoriteResponse
ObjectSetIsArchived(context.Context, *pb.RpcObjectSetIsArchivedRequest) *pb.RpcObjectSetIsArchivedResponse
ObjectSetSource(context.Context, *pb.RpcObjectSetSourceRequest) *pb.RpcObjectSetSourceResponse
ObjectListDuplicate(context.Context, *pb.RpcObjectListDuplicateRequest) *pb.RpcObjectListDuplicateResponse
ObjectListDelete(context.Context, *pb.RpcObjectListDeleteRequest) *pb.RpcObjectListDeleteResponse
ObjectListSetIsArchived(context.Context, *pb.RpcObjectListSetIsArchivedRequest) *pb.RpcObjectListSetIsArchivedResponse
@ -408,6 +425,19 @@ type ClientCommandsHandler interface {
BlockDataviewRelationListAvailable(context.Context, *pb.RpcBlockDataviewRelationListAvailableRequest) *pb.RpcBlockDataviewRelationListAvailableResponse
BlockDataviewGroupOrderUpdate(context.Context, *pb.RpcBlockDataviewGroupOrderUpdateRequest) *pb.RpcBlockDataviewGroupOrderUpdateResponse
BlockDataviewObjectOrderUpdate(context.Context, *pb.RpcBlockDataviewObjectOrderUpdateRequest) *pb.RpcBlockDataviewObjectOrderUpdateResponse
BlockDataviewCreateFromExistingObject(context.Context, *pb.RpcBlockDataviewCreateFromExistingObjectRequest) *pb.RpcBlockDataviewCreateFromExistingObjectResponse
BlockDataviewFilterAdd(context.Context, *pb.RpcBlockDataviewFilterAddRequest) *pb.RpcBlockDataviewFilterAddResponse
BlockDataviewFilterRemove(context.Context, *pb.RpcBlockDataviewFilterRemoveRequest) *pb.RpcBlockDataviewFilterRemoveResponse
BlockDataviewFilterReplace(context.Context, *pb.RpcBlockDataviewFilterReplaceRequest) *pb.RpcBlockDataviewFilterReplaceResponse
BlockDataviewFilterSort(context.Context, *pb.RpcBlockDataviewFilterSortRequest) *pb.RpcBlockDataviewFilterSortResponse
BlockDataviewSortAdd(context.Context, *pb.RpcBlockDataviewSortAddRequest) *pb.RpcBlockDataviewSortAddResponse
BlockDataviewSortRemove(context.Context, *pb.RpcBlockDataviewSortRemoveRequest) *pb.RpcBlockDataviewSortRemoveResponse
BlockDataviewSortReplace(context.Context, *pb.RpcBlockDataviewSortReplaceRequest) *pb.RpcBlockDataviewSortReplaceResponse
BlockDataviewSortSort(context.Context, *pb.RpcBlockDataviewSortSortRequest) *pb.RpcBlockDataviewSortSortResponse
BlockDataviewViewRelationAdd(context.Context, *pb.RpcBlockDataviewViewRelationAddRequest) *pb.RpcBlockDataviewViewRelationAddResponse
BlockDataviewViewRelationRemove(context.Context, *pb.RpcBlockDataviewViewRelationRemoveRequest) *pb.RpcBlockDataviewViewRelationRemoveResponse
BlockDataviewViewRelationReplace(context.Context, *pb.RpcBlockDataviewViewRelationReplaceRequest) *pb.RpcBlockDataviewViewRelationReplaceResponse
BlockDataviewViewRelationSort(context.Context, *pb.RpcBlockDataviewViewRelationSortRequest) *pb.RpcBlockDataviewViewRelationSortResponse
// Simple table block commands
// ***
BlockTableCreate(context.Context, *pb.RpcBlockTableCreateRequest) *pb.RpcBlockTableCreateResponse
@ -1311,6 +1341,26 @@ func ObjectSetIsArchived(b []byte) (resp []byte) {
return resp
}
func ObjectSetSource(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcObjectSetSourceResponse{Error: &pb.RpcObjectSetSourceResponseError{Code: pb.RpcObjectSetSourceResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcObjectSetSourceRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcObjectSetSourceResponse{Error: &pb.RpcObjectSetSourceResponseError{Code: pb.RpcObjectSetSourceResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.ObjectSetSource(context.Background(), in).Marshal()
return resp
}
func ObjectListDuplicate(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
@ -3191,6 +3241,266 @@ func BlockDataviewObjectOrderUpdate(b []byte) (resp []byte) {
return resp
}
func BlockDataviewCreateFromExistingObject(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewCreateFromExistingObjectResponse{Error: &pb.RpcBlockDataviewCreateFromExistingObjectResponseError{Code: pb.RpcBlockDataviewCreateFromExistingObjectResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewCreateFromExistingObjectRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewCreateFromExistingObjectResponse{Error: &pb.RpcBlockDataviewCreateFromExistingObjectResponseError{Code: pb.RpcBlockDataviewCreateFromExistingObjectResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewCreateFromExistingObject(context.Background(), in).Marshal()
return resp
}
func BlockDataviewFilterAdd(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewFilterAddResponse{Error: &pb.RpcBlockDataviewFilterAddResponseError{Code: pb.RpcBlockDataviewFilterAddResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewFilterAddRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewFilterAddResponse{Error: &pb.RpcBlockDataviewFilterAddResponseError{Code: pb.RpcBlockDataviewFilterAddResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewFilterAdd(context.Background(), in).Marshal()
return resp
}
func BlockDataviewFilterRemove(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewFilterRemoveResponse{Error: &pb.RpcBlockDataviewFilterRemoveResponseError{Code: pb.RpcBlockDataviewFilterRemoveResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewFilterRemoveRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewFilterRemoveResponse{Error: &pb.RpcBlockDataviewFilterRemoveResponseError{Code: pb.RpcBlockDataviewFilterRemoveResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewFilterRemove(context.Background(), in).Marshal()
return resp
}
func BlockDataviewFilterReplace(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewFilterReplaceResponse{Error: &pb.RpcBlockDataviewFilterReplaceResponseError{Code: pb.RpcBlockDataviewFilterReplaceResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewFilterReplaceRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewFilterReplaceResponse{Error: &pb.RpcBlockDataviewFilterReplaceResponseError{Code: pb.RpcBlockDataviewFilterReplaceResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewFilterReplace(context.Background(), in).Marshal()
return resp
}
func BlockDataviewFilterSort(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewFilterSortResponse{Error: &pb.RpcBlockDataviewFilterSortResponseError{Code: pb.RpcBlockDataviewFilterSortResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewFilterSortRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewFilterSortResponse{Error: &pb.RpcBlockDataviewFilterSortResponseError{Code: pb.RpcBlockDataviewFilterSortResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewFilterSort(context.Background(), in).Marshal()
return resp
}
func BlockDataviewSortAdd(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewSortAddResponse{Error: &pb.RpcBlockDataviewSortAddResponseError{Code: pb.RpcBlockDataviewSortAddResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewSortAddRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewSortAddResponse{Error: &pb.RpcBlockDataviewSortAddResponseError{Code: pb.RpcBlockDataviewSortAddResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewSortAdd(context.Background(), in).Marshal()
return resp
}
func BlockDataviewSortRemove(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewSortRemoveResponse{Error: &pb.RpcBlockDataviewSortRemoveResponseError{Code: pb.RpcBlockDataviewSortRemoveResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewSortRemoveRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewSortRemoveResponse{Error: &pb.RpcBlockDataviewSortRemoveResponseError{Code: pb.RpcBlockDataviewSortRemoveResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewSortRemove(context.Background(), in).Marshal()
return resp
}
func BlockDataviewSortReplace(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewSortReplaceResponse{Error: &pb.RpcBlockDataviewSortReplaceResponseError{Code: pb.RpcBlockDataviewSortReplaceResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewSortReplaceRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewSortReplaceResponse{Error: &pb.RpcBlockDataviewSortReplaceResponseError{Code: pb.RpcBlockDataviewSortReplaceResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewSortReplace(context.Background(), in).Marshal()
return resp
}
func BlockDataviewSortSort(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewSortSortResponse{Error: &pb.RpcBlockDataviewSortSortResponseError{Code: pb.RpcBlockDataviewSortSortResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewSortSortRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewSortSortResponse{Error: &pb.RpcBlockDataviewSortSortResponseError{Code: pb.RpcBlockDataviewSortSortResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewSortSort(context.Background(), in).Marshal()
return resp
}
func BlockDataviewViewRelationAdd(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewViewRelationAddResponse{Error: &pb.RpcBlockDataviewViewRelationAddResponseError{Code: pb.RpcBlockDataviewViewRelationAddResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewViewRelationAddRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewViewRelationAddResponse{Error: &pb.RpcBlockDataviewViewRelationAddResponseError{Code: pb.RpcBlockDataviewViewRelationAddResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewViewRelationAdd(context.Background(), in).Marshal()
return resp
}
func BlockDataviewViewRelationRemove(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewViewRelationRemoveResponse{Error: &pb.RpcBlockDataviewViewRelationRemoveResponseError{Code: pb.RpcBlockDataviewViewRelationRemoveResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewViewRelationRemoveRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewViewRelationRemoveResponse{Error: &pb.RpcBlockDataviewViewRelationRemoveResponseError{Code: pb.RpcBlockDataviewViewRelationRemoveResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewViewRelationRemove(context.Background(), in).Marshal()
return resp
}
func BlockDataviewViewRelationReplace(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewViewRelationReplaceResponse{Error: &pb.RpcBlockDataviewViewRelationReplaceResponseError{Code: pb.RpcBlockDataviewViewRelationReplaceResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewViewRelationReplaceRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewViewRelationReplaceResponse{Error: &pb.RpcBlockDataviewViewRelationReplaceResponseError{Code: pb.RpcBlockDataviewViewRelationReplaceResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewViewRelationReplace(context.Background(), in).Marshal()
return resp
}
func BlockDataviewViewRelationSort(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
if r := recover(); r != nil {
resp, _ = (&pb.RpcBlockDataviewViewRelationSortResponse{Error: &pb.RpcBlockDataviewViewRelationSortResponseError{Code: pb.RpcBlockDataviewViewRelationSortResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
PanicHandler(r)
}
}
}()
in := new(pb.RpcBlockDataviewViewRelationSortRequest)
if err := in.Unmarshal(b); err != nil {
resp, _ = (&pb.RpcBlockDataviewViewRelationSortResponse{Error: &pb.RpcBlockDataviewViewRelationSortResponseError{Code: pb.RpcBlockDataviewViewRelationSortResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
return resp
}
resp, _ = clientCommandsHandler.BlockDataviewViewRelationSort(context.Background(), in).Marshal()
return resp
}
func BlockTableCreate(b []byte) (resp []byte) {
defer func() {
if PanicHandler != nil {
@ -3903,6 +4213,8 @@ func CommandAsync(cmd string, data []byte, callback func(data []byte)) {
cd = ObjectSetIsFavorite(data)
case "ObjectSetIsArchived":
cd = ObjectSetIsArchived(data)
case "ObjectSetSource":
cd = ObjectSetSource(data)
case "ObjectListDuplicate":
cd = ObjectListDuplicate(data)
case "ObjectListDelete":
@ -4091,6 +4403,32 @@ func CommandAsync(cmd string, data []byte, callback func(data []byte)) {
cd = BlockDataviewGroupOrderUpdate(data)
case "BlockDataviewObjectOrderUpdate":
cd = BlockDataviewObjectOrderUpdate(data)
case "BlockDataviewCreateFromExistingObject":
cd = BlockDataviewCreateFromExistingObject(data)
case "BlockDataviewFilterAdd":
cd = BlockDataviewFilterAdd(data)
case "BlockDataviewFilterRemove":
cd = BlockDataviewFilterRemove(data)
case "BlockDataviewFilterReplace":
cd = BlockDataviewFilterReplace(data)
case "BlockDataviewFilterSort":
cd = BlockDataviewFilterSort(data)
case "BlockDataviewSortAdd":
cd = BlockDataviewSortAdd(data)
case "BlockDataviewSortRemove":
cd = BlockDataviewSortRemove(data)
case "BlockDataviewSortReplace":
cd = BlockDataviewSortReplace(data)
case "BlockDataviewSortSort":
cd = BlockDataviewSortSort(data)
case "BlockDataviewViewRelationAdd":
cd = BlockDataviewViewRelationAdd(data)
case "BlockDataviewViewRelationRemove":
cd = BlockDataviewViewRelationRemove(data)
case "BlockDataviewViewRelationReplace":
cd = BlockDataviewViewRelationReplace(data)
case "BlockDataviewViewRelationSort":
cd = BlockDataviewViewRelationSort(data)
case "BlockTableCreate":
cd = BlockTableCreate(data)
case "BlockTableExpand":

View file

@ -48,7 +48,7 @@ type Service interface {
}
type ObjectCreator interface {
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, relationIds []string, s *state.State) (id string, newDetails *types.Struct, err error)
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, s *state.State) (id string, newDetails *types.Struct, err error)
}
type DetailsSetter interface {
@ -120,7 +120,7 @@ func (s *service) CreateBookmarkObject(details *types.Struct, getContent Content
objectId = rec.Details.Fields[bundle.RelationKeyId.String()].GetStringValue()
} else {
details.Fields[bundle.RelationKeyType.String()] = pbtypes.String(bundle.TypeKeyBookmark.URL())
objectId, newDetails, err = s.creator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypePage, details, nil, nil)
objectId, newDetails, err = s.creator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypePage, details, nil)
if err != nil {
return "", nil, fmt.Errorf("create bookmark object: %w", err)
}

View file

@ -30,7 +30,7 @@ func (s *Service) TemplateCreateFromObject(id string) (templateID string, err er
return
}
templateID, _, err = s.objectCreator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeTemplate, nil, nil, st)
templateID, _, err = s.objectCreator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeTemplate, nil, st)
if err != nil {
return
}
@ -56,7 +56,7 @@ func (s *Service) TemplateClone(id string) (templateID string, err error) {
}); err != nil {
return
}
templateID, _, err = s.objectCreator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeTemplate, nil, nil, st)
templateID, _, err = s.objectCreator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeTemplate, nil, st)
if err != nil {
return
}
@ -81,7 +81,7 @@ func (s *Service) ObjectDuplicate(id string) (objectID string, err error) {
return
}
objectID, _, err = s.objectCreator.CreateSmartBlockFromState(context.TODO(), sbt, nil, nil, st)
objectID, _, err = s.objectCreator.CreateSmartBlockFromState(context.TODO(), sbt, nil, st)
if err != nil {
return
}
@ -95,7 +95,7 @@ func (s *Service) TemplateCreateFromObjectByObjectType(otID string) (templateID
var st = state.NewDoc("", nil).(*state.State)
st.SetDetail(bundle.RelationKeyTargetObjectType.String(), pbtypes.String(otID))
st.SetObjectTypes([]string{bundle.TypeKeyTemplate.URL(), otID})
templateID, _, err = s.objectCreator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeTemplate, nil, nil, st)
templateID, _, err = s.objectCreator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeTemplate, nil, st)
if err != nil {
return
}
@ -103,13 +103,12 @@ func (s *Service) TemplateCreateFromObjectByObjectType(otID string) (templateID
}
func (s *Service) CreateWorkspace(req *pb.RpcWorkspaceCreateRequest) (workspaceID string, err error) {
id, _, err := s.objectCreator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeWorkspace,
&types.Struct{Fields: map[string]*types.Value{
bundle.RelationKeyName.String(): pbtypes.String(req.Name),
bundle.RelationKeyType.String(): pbtypes.String(bundle.TypeKeySpace.URL()),
bundle.RelationKeyIconEmoji.String(): pbtypes.String("🌎"),
bundle.RelationKeyLayout.String(): pbtypes.Float64(float64(model.ObjectType_space)),
}}, nil, nil)
id, _, err := s.objectCreator.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeWorkspace, &types.Struct{Fields: map[string]*types.Value{
bundle.RelationKeyName.String(): pbtypes.String(req.Name),
bundle.RelationKeyType.String(): pbtypes.String(bundle.TypeKeySpace.URL()),
bundle.RelationKeyIconEmoji.String(): pbtypes.String("🌎"),
bundle.RelationKeyLayout.String(): pbtypes.Float64(float64(model.ObjectType_space)),
}}, nil)
return id, err
}

215
core/block/dataview.go Normal file
View file

@ -0,0 +1,215 @@
package block
import (
"github.com/anytypeio/go-anytype-middleware/core/block/editor/dataview"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/core/session"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
)
func (s *Service) AddDataviewFilter(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
filter *model.BlockContentDataviewFilter,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.AddFilter(viewID, filter)
})
}
func (s *Service) RemoveDataviewFilters(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
filterIDs []string,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.RemoveFilters(viewID, filterIDs)
})
}
func (s *Service) ReplaceDataviewFilter(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
filterID string,
filter *model.BlockContentDataviewFilter,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.ReplaceFilter(viewID, filterID, filter)
})
}
func (s *Service) ReorderDataviewFilters(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
filterIDs []string,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.ReorderFilters(viewID, filterIDs)
})
}
func (s *Service) AddDataviewSort(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
sort *model.BlockContentDataviewSort,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.AddSort(viewID, sort)
})
}
func (s *Service) RemoveDataviewSorts(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
relationKeys []string,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.RemoveSorts(viewID, relationKeys)
})
}
func (s *Service) ReplaceDataviewSort(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
relationKey string,
sort *model.BlockContentDataviewSort,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.ReplaceSort(viewID, relationKey, sort)
})
}
func (s *Service) ReorderDataviewSorts(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
relationKeys []string,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.ReorderSorts(viewID, relationKeys)
})
}
func (s *Service) AddDataviewViewRelation(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
relation *model.BlockContentDataviewRelation,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.AddViewRelation(viewID, relation)
})
}
func (s *Service) RemoveDataviewViewRelations(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
relationKeys []string,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.RemoveViewRelations(viewID, relationKeys)
})
}
func (s *Service) ReplaceDataviewViewRelation(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
relationKey string,
relation *model.BlockContentDataviewRelation,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.ReplaceViewRelation(viewID, relationKey, relation)
})
}
func (s *Service) ReorderDataviewViewRelations(
ctx *session.Context,
contextID string,
blockID string,
viewID string,
relationKeys []string,
) (err error) {
return DoStateCtx(s, ctx, contextID, func(s *state.State, d dataview.Dataview) error {
dv, err := d.GetDataviewBlock(s, blockID)
if err != nil {
return err
}
return dv.ReorderViewRelations(viewID, relationKeys)
})
}

View file

@ -18,6 +18,7 @@ import (
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/stext"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/table"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/template"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/widget"
"github.com/anytypeio/go-anytype-middleware/core/block/simple"
"github.com/anytypeio/go-anytype-middleware/core/block/simple/link"
@ -175,7 +176,7 @@ func (s *Service) GetAggregatedRelations(
func (s *Service) UpdateDataviewView(ctx *session.Context, req pb.RpcBlockDataviewViewUpdateRequest) error {
return s.DoDataview(req.ContextId, func(b dataview.Dataview) error {
return b.UpdateView(ctx, req.BlockId, req.ViewId, *req.View, true)
return b.UpdateView(ctx, req.BlockId, req.ViewId, req.View, true)
})
}
@ -218,7 +219,7 @@ func (s *Service) CreateDataviewView(
if req.View == nil {
req.View = &model.BlockContentDataviewView{}
}
view, e := b.CreateView(ctx, req.BlockId, *req.View)
view, e := b.CreateView(ctx, req.BlockId, *req.View, req.Source)
if e != nil {
return e
}
@ -886,3 +887,39 @@ func (s *Service) CreateWidgetBlock(ctx *session.Context, req *pb.RpcBlockCreate
})
return id, err
}
func (s *Service) CopyDataviewToBlock(ctx *session.Context,
req *pb.RpcBlockDataviewCreateFromExistingObjectRequest) ([]*model.BlockContentDataviewView, error) {
var targetDvContent *model.BlockContentDataview
err := s.DoDataview(req.TargetObjectId, func(d dataview.Dataview) error {
var err error
targetDvContent, err = d.GetDataview(template.DataviewBlockId)
return err
})
if err != nil {
return nil, err
}
err = s.Do(req.ContextId, func(b smartblock.SmartBlock) error {
st := b.NewStateCtx(ctx)
block := st.Get(req.BlockId)
dvContent, ok := block.Model().Content.(*model.BlockContentOfDataview)
if !ok {
return fmt.Errorf("block must contain dataView content")
}
dvContent.Dataview.Views = targetDvContent.Views
dvContent.Dataview.RelationLinks = targetDvContent.RelationLinks
dvContent.Dataview.TargetObjectId = req.TargetObjectId
return b.Apply(st)
})
if err != nil {
return nil, err
}
return targetDvContent.Views, err
}

View file

@ -19,7 +19,7 @@ import (
)
type ObjectCreator interface {
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, relationIds []string, createState *state.State) (id string, newDetails *types.Struct, err error)
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, createState *state.State) (id string, newDetails *types.Struct, err error)
InjectWorkspaceID(details *types.Struct, objectID string)
}
@ -72,7 +72,7 @@ func (bs *basic) ExtractBlocksToObjects(ctx *session.Context, s ObjectCreator, r
det := &types.Struct{Fields: fields}
s.InjectWorkspaceID(det, req.ContextId)
objectID, _, err := s.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypePage, det, nil, objState)
objectID, _, err := s.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypePage, det, objState)
if err != nil {
return nil, fmt.Errorf("create child object: %w", err)
}

View file

@ -26,7 +26,7 @@ func (t testExtractObjects) Add(object *smarttest.SmartTest) {
t.objects[object.Id()] = object
}
func (t testExtractObjects) CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, relationIds []string, createState *state.State) (id string, newDetails *types.Struct, err error) {
func (t testExtractObjects) CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, createState *state.State) (id string, newDetails *types.Struct, err error) {
id = bson.NewObjectId().Hex()
object := smarttest.New(id)
t.objects[id] = object

View file

@ -52,16 +52,20 @@ type Dataview interface {
// GetAggregatedRelations(blockId string) ([]*model.Relation, error)
GetDataviewRelations(blockId string) ([]*model.Relation, error)
GetDataview(blockID string) (*model.BlockContentDataview, error)
DeleteView(ctx *session.Context, blockId string, viewId string, showEvent bool) error
SetActiveView(ctx *session.Context, blockId string, activeViewId string, limit int, offset int) error
CreateView(ctx *session.Context, blockId string, view model.BlockContentDataviewView) (*model.BlockContentDataviewView, error)
CreateView(ctx *session.Context, blockID string,
view model.BlockContentDataviewView, source []string) (*model.BlockContentDataviewView, error)
SetViewPosition(ctx *session.Context, blockId string, viewId string, position uint32) error
AddRelations(ctx *session.Context, blockId string, relationIds []string, showEvent bool) error
DeleteRelations(ctx *session.Context, blockId string, relationIds []string, showEvent bool) error
UpdateView(ctx *session.Context, blockId string, viewId string, view model.BlockContentDataviewView, showEvent bool) error
UpdateView(ctx *session.Context, blockID string, viewID string, view *model.BlockContentDataviewView, showEvent bool) error
UpdateViewGroupOrder(ctx *session.Context, blockId string, order *model.BlockContentDataviewGroupOrder) error
UpdateViewObjectOrder(ctx *session.Context, blockId string, orders []*model.BlockContentDataviewObjectOrder) error
GetDataviewBlock(s *state.State, blockID string) (dataview.Block, error)
}
func NewDataview(
@ -87,6 +91,10 @@ type sdataview struct {
relationService relation2.Service
}
func (d *sdataview) GetDataviewBlock(s *state.State, blockID string) (dataview.Block, error) {
return getDataviewBlock(s, blockID)
}
func (d *sdataview) SetSource(ctx *session.Context, blockId string, source []string) (err error) {
s := d.NewStateCtx(ctx)
if blockId == "" {
@ -174,6 +182,16 @@ func (d *sdataview) GetDataviewRelations(blockId string) ([]*model.Relation, err
return tb.Model().GetDataview().GetRelations(), nil
}
func (d *sdataview) GetDataview(blockID string) (*model.BlockContentDataview, error) {
st := d.NewState()
tb, err := getDataviewBlock(st, blockID)
if err != nil {
return nil, err
}
return tb.Model().GetDataview(), nil
}
func (d *sdataview) DeleteView(ctx *session.Context, blockId string, viewId string, showEvent bool) error {
s := d.NewStateCtx(ctx)
tb, err := getDataviewBlock(s, blockId)
@ -194,14 +212,14 @@ func (d *sdataview) DeleteView(ctx *session.Context, blockId string, viewId stri
return d.Apply(s, smartblock.NoEvent)
}
func (d *sdataview) UpdateView(ctx *session.Context, blockId string, viewId string, view model.BlockContentDataviewView, showEvent bool) error {
func (d *sdataview) UpdateView(ctx *session.Context, blockID string, viewID string, view *model.BlockContentDataviewView, showEvent bool) error {
s := d.NewStateCtx(ctx)
dvBlock, err := getDataviewBlock(s, blockId)
dvBlock, err := getDataviewBlock(s, blockID)
if err != nil {
return err
}
if err = dvBlock.SetView(viewId, view); err != nil {
if err = dvBlock.SetViewFields(viewID, view); err != nil {
return err
}
@ -269,7 +287,8 @@ func (d *sdataview) SetViewPosition(ctx *session.Context, blockId string, viewId
return d.Apply(s)
}
func (d *sdataview) CreateView(ctx *session.Context, id string, view model.BlockContentDataviewView) (*model.BlockContentDataviewView, error) {
func (d *sdataview) CreateView(ctx *session.Context, id string,
view model.BlockContentDataviewView, source []string) (*model.BlockContentDataviewView, error) {
view.Id = uuid.New().String()
s := d.NewStateCtx(ctx)
tb, err := getDataviewBlock(s, id)
@ -277,7 +296,14 @@ func (d *sdataview) CreateView(ctx *session.Context, id string, view model.Block
return nil, err
}
sch, err := d.getSchema(tb)
if len(source) == 0 {
source = pbtypes.GetStringList(s.Details(), bundle.RelationKeySetOf.String())
if len(source) == 0 {
return nil, fmt.Errorf("source not found")
}
}
sch, err := d.getSchema(tb, source)
if err != nil {
return nil, err
}
@ -432,8 +458,8 @@ func SchemaBySources(sources []string, store objectstore.ObjectStore, optionalRe
return nil, fmt.Errorf("relation or type not found")
}
func (d *sdataview) getSchema(dvBlock dataview.Block) (schema.Schema, error) {
return SchemaBySources(dvBlock.Model().GetDataview().Source, d.objectStore, dvBlock.Model().GetDataview().RelationLinks)
func (d *sdataview) getSchema(dvBlock dataview.Block, source []string) (schema.Schema, error) {
return SchemaBySources(source, d.objectStore, dvBlock.Model().GetDataview().RelationLinks)
}
func (d *sdataview) checkDVBlocks(info smartblock.ApplyInfo) (err error) {
@ -619,7 +645,6 @@ func DataviewBlockBySource(store objectstore.ObjectStore, source []string) (res
res = model.BlockContentOfDataview{
Dataview: &model.BlockContentDataview{
RelationLinks: relations,
Source: source,
Views: []*model.BlockContentDataviewView{
{
Id: bson.NewObjectId().Hex(),

View file

@ -126,12 +126,7 @@ func (f *ObjectFactory) New(sbType model.SmartBlockType) smartblock.SmartBlock {
f.relationService,
)
case model.SmartBlockType_SubObject:
return NewSubObject(
f.objectStore,
f.fileBlockService,
f.anytype,
f.relationService,
)
panic("subobject not supported via factory")
case model.SmartBlockType_File:
return NewFiles()
case model.SmartBlockType_MarketplaceType:

View file

@ -209,6 +209,10 @@ func (t *ObjectType) Init(ctx *smartblock.InitContext) (err error) {
}
fixMissingSmartblockTypes := func(s *state.State) {
if isBundled {
return
}
// we have a bug in internal release that was not adding smartblocktype to newly created custom types
currTypes := pbtypes.GetIntList(s.Details(), bundle.RelationKeySmartblockTypes.String())
sourceObject := pbtypes.GetString(s.Details(), bundle.RelationKeySourceObject.String())
@ -230,8 +234,15 @@ func (t *ObjectType) Init(ctx *smartblock.InitContext) (err error) {
}
}
var objectType string
if isBundled {
objectType = bundle.TypeKeyObjectType.BundledURL()
} else {
objectType = bundle.TypeKeyObjectType.URL()
}
return smartblock.ObjectApplyTemplate(t, ctx.State,
template.WithObjectTypesAndLayout([]string{bundle.TypeKeyObjectType.URL()}, model.ObjectType_objectType),
template.WithForcedObjectTypes([]string{objectType}),
template.WithForcedDetail(bundle.RelationKeyLayout, pbtypes.Float64(float64(model.ObjectType_objectType))),
template.WithEmpty,
template.WithTitle,
template.WithDefaultFeaturedRelations,

View file

@ -13,7 +13,6 @@ import (
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore/objectstore"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
"github.com/anytypeio/go-anytype-middleware/util/slice"
)
type Set struct {
@ -53,25 +52,21 @@ func (p *Set) Init(ctx *smartblock.InitContext) (err error) {
return err
}
var featuredRelations []string
if ctx.State != nil {
featuredRelations = pbtypes.GetStringList(ctx.State.Details(), bundle.RelationKeyFeaturedRelations.String())
}
// Add missing required featured relations
featuredRelations = slice.Union(featuredRelations, []string{bundle.RelationKeyDescription.String(), bundle.RelationKeyType.String(), bundle.RelationKeySetOf.String()})
featuredRelations = slice.Remove(featuredRelations, bundle.RelationKeyCreator.String())
templates := []template.StateTransformer{
template.WithDataviewRelationMigrationRelation(template.DataviewBlockId, bundle.TypeKeyBookmark.URL(), bundle.RelationKeyUrl, bundle.RelationKeySource),
template.WithObjectTypesAndLayout([]string{bundle.TypeKeySet.URL()}, model.ObjectType_set),
template.WithRelations([]bundle.RelationKey{bundle.RelationKeySetOf}),
template.WithDescription,
template.WithDetail(bundle.RelationKeyFeaturedRelations, pbtypes.StringList(featuredRelations)),
template.WithFeaturedRelations,
template.WithDefaultFeaturedRelations,
template.WithBlockEditRestricted(p.Id()),
}
if dvBlock := p.Pick(template.DataviewBlockId); dvBlock != nil {
setOf := dvBlock.Model().GetDataview().GetSource()
if len(pbtypes.GetStringList(p.Details(), bundle.RelationKeySetOf.String())) > 0 {
setOf = pbtypes.GetStringList(p.Details(), bundle.RelationKeySetOf.String())
}
if len(setOf) == 0 {
log.With("thread", p.Id()).With("sbType", p.SmartBlock.Type().String()).Errorf("dataview has an empty source")
} else {
@ -104,6 +99,7 @@ func (p *Set) Init(ctx *smartblock.InitContext) (err error) {
}
// add missing done relation
templates = append(templates, template.WithDataviewRequiredRelation(template.DataviewBlockId, bundle.RelationKeyDone))
templates = append(templates, template.WithDataviewAddIDsToFilters(template.DataviewBlockId))
}
templates = append(templates, template.WithTitle)
return smartblock.ObjectApplyTemplate(p, ctx.State, templates...)

View file

@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"sort"
"strings"
"sync"
"time"
@ -131,7 +130,7 @@ type SmartBlock interface {
type InitContext struct {
Source source.Source
ObjectTypeUrls []string
RelationIds []string
RelationKeys []string
State *state.State
Relations []*model.Relation
Restriction restriction.Service
@ -256,7 +255,7 @@ func (sb *smartBlock) Init(ctx *InitContext) (err error) {
return err
}
}
if err = sb.addRelations(ctx.State, ctx.RelationIds...); err != nil {
if err = sb.addRelations(ctx.State, ctx.RelationKeys...); err != nil {
return
}
@ -383,37 +382,6 @@ func (sb *smartBlock) fetchMeta() (details []*model.ObjectViewDetailsSet, object
addObjectTypesByDetails(rec.Details)
}
if sb.Type() == model.SmartBlockType_Set {
// add the object type from the dataview source
if b := sb.Doc.Pick("dataview"); b != nil {
if dv := b.Model().GetDataview(); dv != nil {
if len(dv.Source) == 0 || dv.Source[0] == "" {
panic("empty dv source")
}
uniqueObjTypes = append(uniqueObjTypes, dv.Source...)
for _, rel := range dv.Relations {
if rel.Format == model.RelationFormat_file || rel.Format == model.RelationFormat_object {
if rel.Key == bundle.RelationKeyId.String() || rel.Key == bundle.RelationKeyType.String() {
continue
}
for _, ot := range rel.ObjectTypes {
if slice.FindPos(uniqueObjTypes, ot) == -1 {
if ot == "" {
log.Errorf("dv relation %s(%s) has empty obj types", rel.Key, rel.Name)
} else {
if strings.HasPrefix(ot, "http") {
log.Errorf("dv rels has http source")
}
uniqueObjTypes = append(uniqueObjTypes, ot)
}
}
}
}
}
}
}
}
objectTypes, _ = objectstore.GetObjectTypes(sb.objectStore, uniqueObjTypes)
go sb.metaListener(recordsCh)
return

View file

@ -524,6 +524,10 @@ func (s *State) fillChanges(msgs []simple.EventMessage) {
delRelIds = append(delRelIds, msg.Msg.GetObjectRelationsRemove().RelationKeys...)
case *pb.EventMessageValueOfBlockDataViewObjectOrderUpdate:
updMsgs = append(updMsgs, msg.Msg)
case *pb.EventMessageValueOfBlockDataviewViewUpdate:
updMsgs = append(updMsgs, msg.Msg)
case *pb.EventMessageValueOfBlockDataviewTargetObjectIdSet:
updMsgs = append(updMsgs, msg.Msg)
default:
log.Errorf("unexpected event - can't convert to changes: %v", msg.Msg)
}

View file

@ -19,7 +19,6 @@ import (
"github.com/anytypeio/go-anytype-middleware/core/relation/relationutils"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
"github.com/anytypeio/go-anytype-middleware/util/slice"
)
@ -255,26 +254,26 @@ func (s *State) applyEvent(ev *pb.EventMessage) (err error) {
event := o.BlockDataViewObjectOrderUpdate
if err = apply(event.Id, func(b simple.Block) error {
if dvBlock, ok := b.(dataview.Block); ok {
var existOrder []string
for _, order := range dvBlock.Model().GetDataview().ObjectOrders {
if order.ViewId == event.ViewId && order.GroupId == event.GroupId {
existOrder = order.ObjectIds
}
}
changes := o.BlockDataViewObjectOrderUpdate.GetSliceChanges()
changedIds := slice.ApplyChanges(existOrder, pbtypes.EventsToSliceChange(changes))
dvBlock.SetViewObjectOrder([]*model.BlockContentDataviewObjectOrder{
{ViewId: event.ViewId, GroupId: event.GroupId, ObjectIds: changedIds},
})
dvBlock.ApplyObjectOrderUpdate(event)
return nil
}
return fmt.Errorf("not a dataview block")
}); err != nil {
return
}
case *pb.EventMessageValueOfBlockDataviewViewUpdate:
ev := o.BlockDataviewViewUpdate
if err = apply(ev.Id, func(b simple.Block) error {
if dvBlock, ok := b.(dataview.Block); ok {
dvBlock.ApplyViewUpdate(ev)
return nil
}
return fmt.Errorf("not a dataview block")
}); err != nil {
return
}
case *pb.EventMessageValueOfBlockSetWidget:
if err = apply(o.BlockSetWidget.Id, func(b simple.Block) error {
if tr, ok := b.(widget.Block); ok {
@ -284,6 +283,16 @@ func (s *State) applyEvent(ev *pb.EventMessage) (err error) {
}); err != nil {
return
}
case *pb.EventMessageValueOfBlockDataviewTargetObjectIdSet:
if err = apply(o.BlockDataviewTargetObjectIdSet.Id, func(b simple.Block) error {
if dvBlock, ok := b.(dataview.Block); ok {
dvBlock.SetTargetObjectID(o.BlockDataviewTargetObjectIdSet.TargetObjectId)
return nil
}
return fmt.Errorf("not a dataview block")
}); err != nil {
return
}
}
return nil

View file

@ -872,14 +872,6 @@ func (s *State) SetObjectTypesToMigrate(objectTypes []string) *State {
}
func (s *State) InjectDerivedDetails() {
if objTypes := s.ObjectTypes(); len(objTypes) > 0 && objTypes[0] == bundle.TypeKeySet.URL() {
if b := s.Get("dataview"); b != nil {
source := b.Model().GetDataview().GetSource()
s.SetLocalDetail(bundle.RelationKeySetOf.String(), pbtypes.StringList(source))
} else {
s.SetLocalDetail(bundle.RelationKeySetOf.String(), pbtypes.StringList([]string{}))
}
}
s.SetDetailAndBundledRelation(bundle.RelationKeyId, pbtypes.String(s.RootId()))
if ot := s.ObjectType(); ot != "" {
@ -1267,37 +1259,24 @@ func (s *State) Copy() *State {
objTypesToMigrate := make([]string, len(s.ObjectTypesToMigrate()))
copy(objTypesToMigrate, s.ObjectTypesToMigrate())
agOptsCopy := make(map[string][]*model.RelationOption, len(s.AggregatedOptionsByRelation()))
for k, v := range s.AggregatedOptionsByRelation() {
agOptsCopy[k] = pbtypes.CopyRelationOptions(v)
}
relationLinks := make([]*model.RelationLink, len(s.relationLinks))
for i, rl := range s.relationLinks {
relationLinks[i] = &model.RelationLink{
Format: rl.Format,
Key: rl.Key,
}
}
storeKeyRemoved := s.StoreKeysRemoved()
storeKeyRemovedCopy := make(map[string]struct{}, len(storeKeyRemoved))
for i := range storeKeyRemoved {
storeKeyRemovedCopy[i] = struct{}{}
}
copy := &State{
ctx: s.ctx,
blocks: blocks,
rootId: s.rootId,
details: pbtypes.CopyStruct(s.Details()),
localDetails: pbtypes.CopyStruct(s.LocalDetails()),
relationLinks: relationLinks,
extraRelations: pbtypes.CopyRelations(s.OldExtraRelations()),
aggregatedOptionsByRelation: agOptsCopy,
objectTypes: objTypes,
objectTypesToMigrate: objTypesToMigrate,
noObjectType: s.noObjectType,
store: pbtypes.CopyStruct(s.Store()),
storeKeyRemoved: storeKeyRemovedCopy,
ctx: s.ctx,
blocks: blocks,
rootId: s.rootId,
details: pbtypes.CopyStruct(s.Details()),
localDetails: pbtypes.CopyStruct(s.LocalDetails()),
relationLinks: s.GetRelationLinks(), // Get methods copy inside
extraRelations: pbtypes.CopyRelations(s.OldExtraRelations()),
objectTypes: objTypes,
objectTypesToMigrate: objTypesToMigrate,
noObjectType: s.noObjectType,
store: pbtypes.CopyStruct(s.Store()),
storeKeyRemoved: storeKeyRemovedCopy,
}
return copy
}

View file

@ -2,7 +2,6 @@ package editor
import (
"fmt"
"strings"
"github.com/gogo/protobuf/types"
@ -26,6 +25,8 @@ import (
)
type SubObject struct {
forcedObjectType bundle.TypeKey
smartblock.SmartBlock
basic.AllOperations
@ -40,6 +41,7 @@ func NewSubObject(
fileBlockService file.BlockService,
anytype core.Service,
relationService relation2.Service,
forcedObjectType bundle.TypeKey,
) *SubObject {
sb := smartblock.New()
return &SubObject{
@ -65,32 +67,36 @@ func NewSubObject(
objectStore,
relationService,
),
forcedObjectType: forcedObjectType,
}
}
func (o *SubObject) Init(ctx *smartblock.InitContext) (err error) {
objectType := o.forcedObjectType
if objectType == "" {
if len(ctx.ObjectTypeUrls) == 1 {
objectType, err = bundle.TypeKeyFromUrl(ctx.ObjectTypeUrls[0])
if err != nil {
return err
}
} else {
return fmt.Errorf("missing object type for subobject")
}
}
if err = o.SmartBlock.Init(ctx); err != nil {
return
}
ot := pbtypes.GetString(ctx.State.CombinedDetails(), bundle.RelationKeyType.String())
if strings.HasPrefix(ot, addr.BundledObjectTypeURLPrefix) {
ot = addr.ObjectTypeKeyToIdPrefix + strings.TrimPrefix(ot, addr.BundledObjectTypeURLPrefix)
}
if strings.HasPrefix(ot, addr.BundledRelationURLPrefix) {
ot = addr.RelationKeyToIdPrefix + strings.TrimPrefix(ot, addr.BundledRelationURLPrefix)
}
switch ot {
case addr.ObjectTypeKeyToIdPrefix + bundle.TypeKeyRelation.String():
switch objectType {
case bundle.TypeKeyRelation:
return o.initRelation(ctx.State)
case addr.ObjectTypeKeyToIdPrefix + bundle.TypeKeyObjectType.String():
case bundle.TypeKeyObjectType:
panic("not implemented") // should never happen because objectType case proceed by ObjectType implementation
case addr.ObjectTypeKeyToIdPrefix + bundle.TypeKeyRelationOption.String():
case bundle.TypeKeyRelationOption:
return o.initRelationOption(ctx.State)
default:
return fmt.Errorf("unknown subobject type %s", ot)
return fmt.Errorf("unknown subobject type %s", objectType)
}
}
@ -126,6 +132,14 @@ func (o *SubObject) initRelation(st *state.State) error {
}
}
maxCountForStatus := func(s *state.State) {
if f := pbtypes.GetFloat64(s.Details(), bundle.RelationKeyRelationFormat.String()); int32(f) == int32(model.RelationFormat_status) {
if maxCount := pbtypes.GetFloat64(s.Details(), bundle.RelationKeyRelationMaxCount.String()); maxCount == 0 {
s.SetDetail(bundle.RelationKeyRelationMaxCount.String(), pbtypes.Int64(1))
}
}
}
relKey := pbtypes.GetString(st.Details(), bundle.RelationKeyRelationKey.String())
dataview := model.BlockContentOfDataview{
Dataview: &model.BlockContentDataview{
@ -160,25 +174,18 @@ func (o *SubObject) initRelation(st *state.State) error {
template.WithAllBlocksEditsRestricted,
template.WithForcedDetail(bundle.RelationKeyLayout, pbtypes.Int64(int64(model.ObjectType_relation))),
template.WithForcedDetail(bundle.RelationKeyIsReadonly, pbtypes.Bool(false)),
template.WithForcedDetail(bundle.RelationKeyType, pbtypes.String(bundle.TypeKeyRelation.URL())),
template.WithAddedFeaturedRelation(bundle.RelationKeySourceObject),
template.MigrateRelationValue(bundle.RelationKeySource, bundle.RelationKeySourceObject),
template.WithTitle,
template.WithDescription,
fixTypes,
maxCountForStatus,
template.WithDefaultFeaturedRelations,
template.WithDataview(dataview, false))
}
func (o *SubObject) initRelationOption(st *state.State) error {
// temp fix for our internal accounts with inconsistent types (should be removed later)
// todo: remove after release
fixTypes := func(s *state.State) {
if list := pbtypes.GetStringList(s.Details(), bundle.RelationKeyRelationFormatObjectTypes.String()); list != nil {
list, _ = relationutils.MigrateObjectTypeIds(list)
s.SetDetail(bundle.RelationKeyRelationFormatObjectTypes.String(), pbtypes.StringList(list))
}
}
relKey := pbtypes.GetString(st.Details(), bundle.RelationKeyRelationKey.String())
dataview := model.BlockContentOfDataview{
Dataview: &model.BlockContentDataview{
@ -209,8 +216,8 @@ func (o *SubObject) initRelationOption(st *state.State) error {
template.WithAllBlocksEditsRestricted,
template.WithForcedDetail(bundle.RelationKeyLayout, pbtypes.Int64(int64(model.ObjectType_relationOption))),
template.WithForcedDetail(bundle.RelationKeyIsReadonly, pbtypes.Bool(false)),
template.WithForcedDetail(bundle.RelationKeyType, pbtypes.String(bundle.TypeKeyRelationOption.URL())),
template.WithTitle,
fixTypes,
template.WithDefaultFeaturedRelations,
template.WithDataview(dataview, false))
}

View file

@ -285,7 +285,11 @@ func (c *SubObjectCollection) initSubObject(st *state.State, collection string,
case collectionKeyObjectTypes:
subObj = NewObjectType(c.anytype, c.objectStore, c.relationService)
default:
subObj = NewSubObject(c.objectStore, c.fileBlockService, c.anytype, c.relationService)
ot, ok := collectionKeyToObjectType(collection)
if !ok {
return fmt.Errorf("unknown collection '%s'", collection)
}
subObj = NewSubObject(c.objectStore, c.fileBlockService, c.anytype, c.relationService, ot)
}
var fullId string

View file

@ -1,6 +1,7 @@
package template
import (
"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
@ -44,6 +45,23 @@ var WithEmpty = StateTransformer(func(s *state.State) {
})
var WithObjectTypes = func(otypes []string) StateTransformer {
return func(s *state.State) {
if len(s.ObjectTypes()) == 0 {
s.SetObjectTypes(otypes)
}
}
}
var WithForcedObjectTypes = func(otypes []string) StateTransformer {
return func(s *state.State) {
if slice.SortedEquals(s.ObjectTypes(), otypes) {
return
}
s.SetObjectTypes(otypes)
}
}
// WithNoObjectTypes is a special case used only for Archive
var WithNoObjectTypes = func() StateTransformer {
return func(s *state.State) {
@ -262,6 +280,8 @@ var WithDefaultFeaturedRelations = StateTransformer(func(s *state.State) {
layout, _ := s.Layout()
if layout == model.ObjectType_basic || layout == model.ObjectType_note {
fr = []string{bundle.RelationKeyType.String()}
} else if layout == model.ObjectType_set {
fr = []string{bundle.RelationKeyDescription.String(), bundle.RelationKeyType.String(), bundle.RelationKeySetOf.String()}
}
s.SetDetail(bundle.RelationKeyFeaturedRelations.String(), pbtypes.StringList(fr))
}
@ -541,9 +561,44 @@ var WithDataviewRelationMigrationRelation = func(id string, source string, from
}
}
var WithDataviewAddIDsToFilters = func(id string) StateTransformer {
return func(s *state.State) {
b := s.Get(id)
if b == nil {
return
}
dv := b.Model().GetDataview()
if dv == nil {
return
}
for _, view := range dv.Views {
for _, f := range view.Filters {
if f.Id == "" {
f.Id = bson.NewObjectId().Hex()
}
}
}
}
}
var WithDataviewRequiredRelation = func(id string, key bundle.RelationKey) StateTransformer {
return func(s *state.State) {
found := false
for _, r := range bundle.SystemRelations {
if r.String() == key.String() {
found = true
break
}
}
rel := bundle.MustGetRelation(key)
if rel == nil {
return
}
if !found {
log.Errorf("WithDataviewRequiredRelation got not system relation %s; ignore", key)
return
}
b := s.Get(id)
if b == nil {
return
@ -557,10 +612,11 @@ var WithDataviewRequiredRelation = func(id string, key bundle.RelationKey) State
if dv == nil {
return
}
if exRel := pbtypes.GetRelation(dv.Relations, key.String()); exRel == nil {
dv.Relations = append(dv.Relations, rel)
if slice.FindPos(pbtypes.GetRelationListKeys(dv.RelationLinks), key.String()) == -1 {
dv.RelationLinks = append(dv.RelationLinks, &model.RelationLink{Key: key.String(), Format: rel.Format})
blockNeedToUpdate = true
}
for i, view := range dv.Views {
if view.Relations == nil {
continue
@ -578,7 +634,6 @@ var WithDataviewRequiredRelation = func(id string, key bundle.RelationKey) State
}
}
if blockNeedToUpdate {
log.Errorf("add missing done relation for set")
s.Set(simple.New(&model.Block{Content: &model.BlockContentOfDataview{Dataview: dv}, Id: id}))
}
}
@ -600,12 +655,12 @@ var WithDataviewID = func(id string, dataview model.BlockContentOfDataview, forc
forceViews && len(dvBlock.Model().GetDataview().Relations) != len(dataview.Dataview.Relations) ||
forceViews && !pbtypes.DataviewViewsEqualSorted(dvBlock.Model().GetDataview().Views, dataview.Dataview.Views) {
log.With("thread", s.RootId()).With("name", pbtypes.GetString(s.Details(), "name")).Warnf("dataview needs to be migrated: %v, %v, %v, %v",
len(dvBlock.Model().GetDataview().Relations) == 0,
!slice.UnsortedEquals(dvBlock.Model().GetDataview().Source, dataview.Dataview.Source),
len(dvBlock.Model().GetDataview().Views) == 0,
forceViews && len(dvBlock.Model().GetDataview().Views[0].Filters) != len(dataview.Dataview.Views[0].Filters) ||
forceViews && len(dvBlock.Model().GetDataview().Relations) != len(dataview.Dataview.Relations))
/* log.With("thread", s.RootId()).With("name", pbtypes.GetString(s.Details(), "name")).Warnf("dataview needs to be migrated: %v, %v, %v, %v",
len(dvBlock.Model().GetDataview().Relations) == 0,
!slice.UnsortedEquals(dvBlock.Model().GetDataview().Source, dataview.Dataview.Source),
len(dvBlock.Model().GetDataview().Views) == 0,
forceViews && len(dvBlock.Model().GetDataview().Views[0].Filters) != len(dataview.Dataview.Views[0].Filters) ||
forceViews && len(dvBlock.Model().GetDataview().Relations) != len(dataview.Dataview.Relations)) */
blockNeedToUpdate = true
return false
}

View file

@ -587,7 +587,9 @@ func (w *Workspaces) createRelation(st *state.State, details *types.Struct) (id
id = addr.RelationKeyToIdPrefix + key
object.Fields[bundle.RelationKeyId.String()] = pbtypes.String(id)
object.Fields[bundle.RelationKeyRelationKey.String()] = pbtypes.String(key)
if pbtypes.GetInt64(details, bundle.RelationKeyRelationFormat.String()) == int64(model.RelationFormat_status) {
object.Fields[bundle.RelationKeyRelationMaxCount.String()] = pbtypes.Int64(1)
}
objectTypes := pbtypes.GetStringList(object, bundle.RelationKeyRelationFormatObjectTypes.String())
if len(objectTypes) > 0 {
var objectTypesToMigrate []string
@ -1012,3 +1014,12 @@ func collectionKeyIsSupported(collKey string) bool {
}
return false
}
func collectionKeyToObjectType(collKey string) (bundle.TypeKey, bool) {
for ot, v := range objectTypeToCollection {
if v == collKey {
return ot, true
}
}
return "", false
}

View file

@ -25,7 +25,7 @@ import (
)
type objectCreator interface {
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, relationIds []string, createState *state.State) (id string, newDetails *types.Struct, err error)
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, createState *state.State) (id string, newDetails *types.Struct, err error)
CreateSubObjectInWorkspace(details *types.Struct, workspaceID string) (id string, newDetails *types.Struct, err error)
CreateSubObjectsInWorkspace(details []*types.Struct) (ids []string, objects []*types.Struct, err error)
}
@ -113,7 +113,7 @@ func (oc *ObjectCreator) Create(ctx *session.Context,
}
}()
newID, details, err := oc.objCreator.CreateSmartBlockFromState(context.TODO(), sbType, nil, nil, st)
newID, details, err := oc.objCreator.CreateSmartBlockFromState(context.TODO(), sbType, nil, st)
if err != nil {
return nil, fmt.Errorf("create object '%s'", st.RootId())
}

View file

@ -21,6 +21,7 @@ import (
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
coresb "github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore/addr"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore/objectstore"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/logging"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
@ -75,7 +76,7 @@ type BlockService interface {
StateFromTemplate(templateID, name string) (st *state.State, err error)
}
func (c *Creator) CreateSmartBlockFromTemplate(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, relationIds []string, templateID string) (id string, newDetails *types.Struct, err error) {
func (c *Creator) CreateSmartBlockFromTemplate(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, templateID string) (id string, newDetails *types.Struct, err error) {
var createState *state.State
if templateID != "" {
if createState, err = c.blockService.StateFromTemplate(templateID, pbtypes.GetString(details, bundle.RelationKeyName.String())); err != nil {
@ -84,10 +85,10 @@ func (c *Creator) CreateSmartBlockFromTemplate(ctx context.Context, sbType cores
} else {
createState = state.NewDoc("", nil).NewState()
}
return c.CreateSmartBlockFromState(ctx, sbType, details, relationIds, createState)
return c.CreateSmartBlockFromState(ctx, sbType, details, createState)
}
func (c *Creator) CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, relationIds []string, createState *state.State) (id string, newDetails *types.Struct, err error) {
func (c *Creator) CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, createState *state.State) (id string, newDetails *types.Struct, err error) {
if createState == nil {
createState = state.NewDoc("", nil).(*state.State)
}
@ -107,11 +108,18 @@ func (c *Creator) CreateSmartBlockFromState(ctx context.Context, sbType coresb.S
}
}
var relationKeys []string
var workspaceID string
if details != nil && details.Fields != nil {
for k, v := range details.Fields {
relId := addr.RelationKeyToIdPrefix + k
if _, err2 := c.objectStore.GetRelationById(relId); err != nil {
// check if installed
err = fmt.Errorf("failed to get installed relation %s: %w", relId, err2)
return
}
relationKeys = append(relationKeys, k)
createState.SetDetail(k, v)
// TODO: add relations to relationIds
}
detailsWorkspaceID := details.Fields[bundle.RelationKeyWorkspaceId.String()]
@ -131,17 +139,23 @@ func (c *Creator) CreateSmartBlockFromState(ctx context.Context, sbType coresb.S
createState.SetDetailAndBundledRelation(bundle.RelationKeyCreatedDate, pbtypes.Int64(time.Now().Unix()))
createState.SetDetailAndBundledRelation(bundle.RelationKeyCreator, pbtypes.String(c.anytype.ProfileID()))
ev := &metrics.CreateObjectEvent{
SetDetailsMs: time.Since(startTime).Milliseconds(),
}
ctx = context.WithValue(ctx, eventCreate, ev)
var tid = thread.Undef
if raw := pbtypes.GetString(createState.CombinedDetails(), bundle.RelationKeyId.String()); raw != "" {
tid, err = thread.Decode(raw)
id = pbtypes.GetString(createState.CombinedDetails(), bundle.RelationKeyId.String())
sbt, _ := coresb.SmartBlockTypeFromID(id)
if sbt == coresb.SmartBlockTypeSubObject {
return c.CreateSubObjectInWorkspace(createState.CombinedDetails(), workspaceID)
} else if id != "" {
tid, err = thread.Decode(id)
if err != nil {
log.Errorf("failed to decode thread id from the state: %s", err.Error())
}
}
ev := &metrics.CreateObjectEvent{
SetDetailsMs: time.Since(startTime).Milliseconds(),
}
ctx = context.WithValue(ctx, eventCreate, ev)
csm, err := c.CreateObjectInWorkspace(ctx, workspaceID, tid, sbType)
if err != nil {
err = fmt.Errorf("anytype.CreateBlock error: %v", err)
@ -155,9 +169,10 @@ func (c *Creator) CreateSmartBlockFromState(ctx context.Context, sbType coresb.S
initCtx := &smartblock.InitContext{
ObjectTypeUrls: objectTypes,
State: createState,
RelationIds: relationIds,
RelationKeys: relationKeys,
}
var sb smartblock.SmartBlock
if sb, err = c.objectFactory.InitObject(id, initCtx); err != nil {
return id, nil, err
}
@ -214,6 +229,11 @@ func (c *Creator) CreateSet(req *pb.RpcObjectCreateSetRequest) (setID string, ne
var dvContent model.BlockContentOfDataview
var dvSchema schema.Schema
// TODO remove it, when schema will be refactored
if len(req.Source) == 0 {
req.Source = []string{bundle.TypeKeyPage.URL()}
}
if len(req.Source) != 0 {
if dvContent, dvSchema, err = dataview.DataviewBlockBySource(c.objectStore, req.Source); err != nil {
return
@ -241,7 +261,6 @@ func (c *Creator) CreateSet(req *pb.RpcObjectCreateSetRequest) (setID string, ne
}
}
tmpls = append(tmpls,
template.WithForcedDetail(bundle.RelationKeySetOf, pbtypes.StringList(blockContent.Dataview.Source)),
template.WithDataview(*blockContent, false),
)
}
@ -251,7 +270,7 @@ func (c *Creator) CreateSet(req *pb.RpcObjectCreateSetRequest) (setID string, ne
}
// TODO: here can be a deadlock if this is somehow created from workspace (as set)
return c.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeSet, nil, nil, newState)
return c.CreateSmartBlockFromState(context.TODO(), coresb.SmartBlockTypeSet, nil, newState)
}
// TODO: it must be in another component
@ -300,8 +319,13 @@ func (c *Creator) CreateObject(req block.DetailsGetter, forcedType bundle.TypeKe
details = internalflag.PutToDetails(details, internalFlags)
}
var templateID string
if v, ok := req.(block.TemplateIDGetter); ok {
templateID = v.GetTemplateId()
}
objectType, err := bundle.TypeKeyFromUrl(pbtypes.GetString(details, bundle.RelationKeyType.String()))
if err != nil && forcedType == "" {
if err != nil && forcedType == "" && templateID == "" {
return "", nil, fmt.Errorf("invalid type in details: %w", err)
}
if forcedType != "" {
@ -337,9 +361,5 @@ func (c *Creator) CreateObject(req block.DetailsGetter, forcedType bundle.TypeKe
sbType = coresb.SmartBlockTypeTemplate
}
var templateID string
if v, ok := req.(block.TemplateIDGetter); ok {
templateID = v.GetTemplateId()
}
return c.CreateSmartBlockFromTemplate(context.TODO(), sbType, details, nil, templateID)
return c.CreateSmartBlockFromTemplate(context.TODO(), sbType, details, templateID)
}

View file

@ -88,7 +88,12 @@ type SmartblockOpener interface {
func newOpenedBlock(sb smartblock.SmartBlock) *openedBlock {
var ob = openedBlock{SmartBlock: sb}
if sb.Type() != model.SmartBlockType_Breadcrumbs {
if sb.Type() != model.SmartBlockType_Breadcrumbs &&
sb.Type() != model.SmartBlockType_SubObject &&
sb.Type() != model.SmartBlockType_Date &&
sb.Type() != model.SmartBlockType_BundledRelation &&
sb.Type() != model.SmartBlockType_BundledObjectType &&
sb.Type() != model.SmartBlockType_BundledTemplate {
// decode and store corresponding threadID for appropriate block
if tid, err := thread.Decode(sb.Id()); err != nil {
log.With("thread", sb.Id()).Warnf("can't restore thread ID: %v", err)
@ -109,7 +114,7 @@ func New() *Service {
}
type objectCreator interface {
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, relationIds []string, createState *state.State) (id string, newDetails *types.Struct, err error)
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, createState *state.State) (id string, newDetails *types.Struct, err error)
InjectWorkspaceID(details *types.Struct, objectID string)
CreateObject(req DetailsGetter, forcedType bundle.TypeKey) (id string, details *types.Struct, err error)
@ -635,6 +640,14 @@ func (s *Service) SetPageIsArchived(req pb.RpcObjectSetIsArchivedRequest) (err e
return s.objectLinksCollectionModify(s.anytype.PredefinedBlocks().Archive, req.ContextId, req.IsArchived)
}
func (s *Service) SetSource(ctx *session.Context, req pb.RpcObjectSetSourceRequest) (err error) {
return s.Do(req.ContextId, func(b smartblock.SmartBlock) error {
st := b.NewStateCtx(ctx)
st.SetDetailAndBundledRelation(bundle.RelationKeySetOf, pbtypes.StringList(req.Source))
return b.Apply(st, smartblock.NoRestrictions)
})
}
func (s *Service) checkArchivedRestriction(isArchived bool, objectId string) error {
if !isArchived {
return nil

View file

@ -43,6 +43,7 @@ type Block interface {
simple.Block
GetView(viewID string) (*model.BlockContentDataviewView, error)
SetView(viewID string, view model.BlockContentDataviewView) error
SetViewFields(viewID string, view *model.BlockContentDataviewView) error
AddView(view model.BlockContentDataviewView)
DeleteView(viewID string) error
SetViewOrder(ids []string)
@ -55,6 +56,7 @@ type Block interface {
GetSource() []string
SetSource(source []string) error
SetActiveView(activeView string)
SetTargetObjectID(targetObjectID string)
FillSmartIds(ids []string) []string
HasSmartIds() bool
@ -65,6 +67,24 @@ type Block interface {
UpdateRelationOld(relationKey string, relation model.Relation) error
// DeleteRelationOld DEPRECATED
DeleteRelationOld(relationKey string) error
ApplyViewUpdate(upd *pb.EventBlockDataviewViewUpdate)
ApplyObjectOrderUpdate(upd *pb.EventBlockDataviewObjectOrderUpdate)
AddFilter(viewID string, filter *model.BlockContentDataviewFilter) error
RemoveFilters(viewID string, filterIDs []string) error
ReplaceFilter(viewID string, filterID string, filter *model.BlockContentDataviewFilter) error
ReorderFilters(viewID string, ids []string) error
AddSort(viewID string, sort *model.BlockContentDataviewSort) error
RemoveSorts(viewID string, relationKeys []string) error
ReplaceSort(viewID string, relationKey string, sort *model.BlockContentDataviewSort) error
ReorderSorts(viewID string, relationKeys []string) error
AddViewRelation(viewID string, relation *model.BlockContentDataviewRelation) error
RemoveViewRelations(viewID string, relationKeys []string) error
ReplaceViewRelation(viewID string, relationKey string, relation *model.BlockContentDataviewRelation) error
ReorderViewRelations(viewID string, relationKeys []string) error
}
type Dataview struct {
@ -82,6 +102,12 @@ func (d *Dataview) Copy() simple.Block {
// Validate TODO: add validation rules
func (d *Dataview) Validate() error {
for _, view := range d.content.Views {
if view.Id == "" {
view.Id = bson.NewObjectId().String()
}
}
return nil
}
@ -118,11 +144,11 @@ func (d *Dataview) Diff(b simple.Block) (msgs []simple.EventMessage, err error)
for _, order2 := range dv.content.ObjectOrders {
var found bool
var changes []slice.Change
var changes []*pb.EventBlockDataviewSliceChange
for _, order1 := range d.content.ObjectOrders {
if order1.ViewId == order2.ViewId && order1.GroupId == order2.GroupId {
found = true
changes = slice.Diff(order1.ObjectIds, order2.ObjectIds)
changes = diffViewObjectOrder(order1, order2)
break
}
}
@ -147,7 +173,7 @@ func (d *Dataview) Diff(b simple.Block) (msgs []simple.EventMessage, err error)
Id: dv.Id,
ViewId: order2.ViewId,
GroupId: order2.GroupId,
SliceChanges: pbtypes.SliceChangeToEvents(changes),
SliceChanges: changes,
}}}})
}
}
@ -155,16 +181,42 @@ func (d *Dataview) Diff(b simple.Block) (msgs []simple.EventMessage, err error)
// @TODO: rewrite for optimised compare
for _, view2 := range dv.content.Views {
var found bool
var changed bool
var (
viewFilterChanges []*pb.EventBlockDataviewViewUpdateFilter
viewRelationChanges []*pb.EventBlockDataviewViewUpdateRelation
viewSortChanges []*pb.EventBlockDataviewViewUpdateSort
viewFieldsChange *pb.EventBlockDataviewViewUpdateFields
)
for _, view1 := range d.content.Views {
if view1.Id == view2.Id {
found = true
changed = !proto.Equal(view1, view2)
viewFieldsChange = diffViewFields(view1, view2)
viewFilterChanges = diffViewFilters(view1, view2)
viewRelationChanges = diffViewRelations(view1, view2)
viewSortChanges = diffViewSorts(view1, view2)
break
}
}
if !found || changed {
if len(viewFilterChanges) > 0 || len(viewRelationChanges) > 0 || len(viewSortChanges) > 0 || viewFieldsChange != nil {
msgs = append(msgs,
simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewViewUpdate{
BlockDataviewViewUpdate: &pb.EventBlockDataviewViewUpdate{
Id: dv.Id,
ViewId: view2.Id,
Fields: viewFieldsChange,
Filter: viewFilterChanges,
Relation: viewRelationChanges,
Sort: viewSortChanges,
},
}}})
}
if !found {
msgs = append(msgs,
simple.EventMessage{
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewViewSet{
@ -240,6 +292,17 @@ func (d *Dataview) Diff(b simple.Block) (msgs []simple.EventMessage, err error)
ViewIds: viewIds2,
}}}})
}
if dv.content.TargetObjectId != d.content.TargetObjectId {
msgs = append(msgs,
simple.EventMessage{Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfBlockDataviewTargetObjectIdSet{
BlockDataviewTargetObjectIdSet: &pb.EventBlockDataviewTargetObjectIdSet{
Id: dv.Id,
TargetObjectId: dv.content.TargetObjectId,
}},
}})
}
return
}
@ -248,6 +311,11 @@ func (s *Dataview) AddView(view model.BlockContentDataviewView) {
if view.Id == "" {
view.Id = uuid.New().String()
}
for _, f := range view.Filters {
if f.Id == "" {
f.Id = bson.NewObjectId().Hex()
}
}
s.content.Views = append(s.content.Views, &view)
}
@ -281,31 +349,45 @@ func (s *Dataview) DeleteView(viewID string) error {
}
func (s *Dataview) SetView(viewID string, view model.BlockContentDataviewView) error {
var found bool
for _, v := range s.content.Views {
if v.Id == viewID {
found = true
v.Relations = view.Relations
v.Sorts = view.Sorts
v.Filters = view.Filters
v.Name = view.Name
v.Type = view.Type
v.CoverRelationKey = view.CoverRelationKey
v.HideIcon = view.HideIcon
v.CoverFit = view.CoverFit
v.CardSize = view.CardSize
v.GroupRelationKey = view.GroupRelationKey
v.GroupBackgroundColors = view.GroupBackgroundColors
break
}
v, err := s.GetView(viewID)
if err != nil {
return err
}
if !found {
return ErrViewNotFound
v.Relations = view.Relations
v.Sorts = view.Sorts
v.Filters = view.Filters
v.Name = view.Name
v.Type = view.Type
v.CoverRelationKey = view.CoverRelationKey
v.HideIcon = view.HideIcon
v.CoverFit = view.CoverFit
v.CardSize = view.CardSize
v.GroupRelationKey = view.GroupRelationKey
v.GroupBackgroundColors = view.GroupBackgroundColors
v.PageLimit = view.PageLimit
return nil
}
// SetViewFields updates only simple fields of a view. It doesn't update filters, relations, sorts.
func (d *Dataview) SetViewFields(viewID string, view *model.BlockContentDataviewView) error {
v, err := d.GetView(viewID)
if err != nil {
return err
}
v.Name = view.Name
v.Type = view.Type
v.CoverRelationKey = view.CoverRelationKey
v.HideIcon = view.HideIcon
v.CoverFit = view.CoverFit
v.CardSize = view.CardSize
v.GroupRelationKey = view.GroupRelationKey
v.GroupBackgroundColors = view.GroupBackgroundColors
v.PageLimit = view.PageLimit
return nil
}
@ -313,11 +395,15 @@ func (l *Dataview) FillSmartIds(ids []string) []string {
for _, rl := range l.content.RelationLinks {
ids = append(ids, addr.RelationKeyToIdPrefix+rl.Key)
}
if l.content.TargetObjectId != "" {
ids = append(ids, l.content.TargetObjectId)
}
return ids
}
func (l *Dataview) HasSmartIds() bool {
return len(l.content.RelationLinks) > 0
return len(l.content.RelationLinks) > 0 || l.content.TargetObjectId != ""
}
func (d *Dataview) AddRelation(relation *model.RelationLink) error {
@ -420,6 +506,10 @@ func (d *Dataview) SetActiveView(activeView string) {
d.content.ActiveView = activeView
}
func (d *Dataview) SetTargetObjectID(targetObjectID string) {
d.content.TargetObjectId = targetObjectID
}
func (d *Dataview) SetViewOrder(viewIds []string) {
var newViews = make([]*model.BlockContentDataviewView, 0, len(viewIds))
for _, viewId := range viewIds {

View file

@ -0,0 +1,374 @@
package dataview
import (
"github.com/gogo/protobuf/proto"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/slice"
)
func diffViewFields(a, b *model.BlockContentDataviewView) *pb.EventBlockDataviewViewUpdateFields {
isEqual := a.Type == b.Type &&
a.Name == b.Name &&
a.CoverRelationKey == b.CoverRelationKey &&
a.HideIcon == b.HideIcon &&
a.CardSize == b.CardSize &&
a.CoverFit == b.CoverFit &&
a.GroupRelationKey == b.GroupRelationKey &&
a.GroupBackgroundColors == b.GroupBackgroundColors &&
a.PageLimit == b.PageLimit
if isEqual {
return nil
}
return &pb.EventBlockDataviewViewUpdateFields{
Type: b.Type,
Name: b.Name,
CoverRelationKey: b.CoverRelationKey,
HideIcon: b.HideIcon,
CardSize: b.CardSize,
CoverFit: b.CoverFit,
GroupRelationKey: b.GroupRelationKey,
GroupBackgroundColors: b.GroupBackgroundColors,
PageLimit: b.PageLimit,
}
}
func getViewFilterID(f *model.BlockContentDataviewFilter) string {
return f.Id
}
func isViewFiltersEqual(a, b *model.BlockContentDataviewFilter) bool {
return proto.Equal(a, b)
}
// nolint:dupl
func diffViewFilters(a, b *model.BlockContentDataviewView) []*pb.EventBlockDataviewViewUpdateFilter {
diff := slice.Diff(a.Filters, b.Filters, getViewFilterID, isViewFiltersEqual)
if len(diff) == 0 {
return nil
}
return unwrapChanges(
diff,
func(afterID string, items []*model.BlockContentDataviewFilter) *pb.EventBlockDataviewViewUpdateFilter {
return &pb.EventBlockDataviewViewUpdateFilter{
Operation: &pb.EventBlockDataviewViewUpdateFilterOperationOfAdd{
Add: &pb.EventBlockDataviewViewUpdateFilterAdd{
AfterId: afterID,
Items: items,
},
},
}
},
func(ids []string) *pb.EventBlockDataviewViewUpdateFilter {
return &pb.EventBlockDataviewViewUpdateFilter{
Operation: &pb.EventBlockDataviewViewUpdateFilterOperationOfRemove{
Remove: &pb.EventBlockDataviewViewUpdateFilterRemove{
Ids: ids,
},
},
}
},
func(afterID string, ids []string) *pb.EventBlockDataviewViewUpdateFilter {
return &pb.EventBlockDataviewViewUpdateFilter{
Operation: &pb.EventBlockDataviewViewUpdateFilterOperationOfMove{
Move: &pb.EventBlockDataviewViewUpdateFilterMove{
AfterId: afterID,
Ids: ids,
},
},
}
},
func(id string, item *model.BlockContentDataviewFilter) *pb.EventBlockDataviewViewUpdateFilter {
return &pb.EventBlockDataviewViewUpdateFilter{
Operation: &pb.EventBlockDataviewViewUpdateFilterOperationOfUpdate{
Update: &pb.EventBlockDataviewViewUpdateFilterUpdate{
Id: id,
Item: item,
},
},
}
})
}
func getViewRelationID(f *model.BlockContentDataviewRelation) string {
return f.Key
}
func isViewRelationsEqual(a, b *model.BlockContentDataviewRelation) bool {
return proto.Equal(a, b)
}
// nolint:dupl
func diffViewRelations(a, b *model.BlockContentDataviewView) []*pb.EventBlockDataviewViewUpdateRelation {
diff := slice.Diff(a.Relations, b.Relations, getViewRelationID, isViewRelationsEqual)
if len(diff) == 0 {
return nil
}
return unwrapChanges(
diff,
func(afterID string, items []*model.BlockContentDataviewRelation) *pb.EventBlockDataviewViewUpdateRelation {
return &pb.EventBlockDataviewViewUpdateRelation{
Operation: &pb.EventBlockDataviewViewUpdateRelationOperationOfAdd{
Add: &pb.EventBlockDataviewViewUpdateRelationAdd{
AfterId: afterID,
Items: items,
},
},
}
},
func(ids []string) *pb.EventBlockDataviewViewUpdateRelation {
return &pb.EventBlockDataviewViewUpdateRelation{
Operation: &pb.EventBlockDataviewViewUpdateRelationOperationOfRemove{
Remove: &pb.EventBlockDataviewViewUpdateRelationRemove{
Ids: ids,
},
},
}
},
func(afterID string, ids []string) *pb.EventBlockDataviewViewUpdateRelation {
return &pb.EventBlockDataviewViewUpdateRelation{
Operation: &pb.EventBlockDataviewViewUpdateRelationOperationOfMove{
Move: &pb.EventBlockDataviewViewUpdateRelationMove{
AfterId: afterID,
Ids: ids,
},
},
}
},
func(id string, item *model.BlockContentDataviewRelation) *pb.EventBlockDataviewViewUpdateRelation {
return &pb.EventBlockDataviewViewUpdateRelation{
Operation: &pb.EventBlockDataviewViewUpdateRelationOperationOfUpdate{
Update: &pb.EventBlockDataviewViewUpdateRelationUpdate{
Id: id,
Item: item,
},
},
}
})
}
func getViewSortID(f *model.BlockContentDataviewSort) string {
return f.RelationKey
}
func isViewSortsEqual(a, b *model.BlockContentDataviewSort) bool {
return proto.Equal(a, b)
}
// nolint:dupl
func diffViewSorts(a, b *model.BlockContentDataviewView) []*pb.EventBlockDataviewViewUpdateSort {
diff := slice.Diff(a.Sorts, b.Sorts, getViewSortID, isViewSortsEqual)
if len(diff) == 0 {
return nil
}
return unwrapChanges(
diff,
func(afterID string, items []*model.BlockContentDataviewSort) *pb.EventBlockDataviewViewUpdateSort {
return &pb.EventBlockDataviewViewUpdateSort{
Operation: &pb.EventBlockDataviewViewUpdateSortOperationOfAdd{
Add: &pb.EventBlockDataviewViewUpdateSortAdd{
AfterId: afterID,
Items: items,
},
},
}
},
func(ids []string) *pb.EventBlockDataviewViewUpdateSort {
return &pb.EventBlockDataviewViewUpdateSort{
Operation: &pb.EventBlockDataviewViewUpdateSortOperationOfRemove{
Remove: &pb.EventBlockDataviewViewUpdateSortRemove{
Ids: ids,
},
},
}
},
func(afterID string, ids []string) *pb.EventBlockDataviewViewUpdateSort {
return &pb.EventBlockDataviewViewUpdateSort{
Operation: &pb.EventBlockDataviewViewUpdateSortOperationOfMove{
Move: &pb.EventBlockDataviewViewUpdateSortMove{
AfterId: afterID,
Ids: ids,
},
},
}
},
func(id string, item *model.BlockContentDataviewSort) *pb.EventBlockDataviewViewUpdateSort {
return &pb.EventBlockDataviewViewUpdateSort{
Operation: &pb.EventBlockDataviewViewUpdateSortOperationOfUpdate{
Update: &pb.EventBlockDataviewViewUpdateSortUpdate{
Id: id,
Item: item,
},
},
}
})
}
func (l *Dataview) ApplyViewUpdate(upd *pb.EventBlockDataviewViewUpdate) {
var view *model.BlockContentDataviewView
for _, v := range l.content.Views {
if v.Id == upd.ViewId {
view = v
break
}
}
if view == nil {
return
}
if f := upd.Fields; f != nil {
view.Type = f.Type
view.Name = f.Name
view.CoverRelationKey = f.CoverRelationKey
view.HideIcon = f.HideIcon
view.CardSize = f.CardSize
view.CoverFit = f.CoverFit
view.GroupRelationKey = f.GroupRelationKey
view.GroupBackgroundColors = f.GroupBackgroundColors
view.PageLimit = f.PageLimit
}
{
var changes []slice.Change[*model.BlockContentDataviewRelation]
for _, r := range upd.Relation {
if v := r.GetUpdate(); v != nil {
changes = append(changes, slice.MakeChangeReplace(v.Item, v.Id))
} else if v := r.GetAdd(); v != nil {
changes = append(changes, slice.MakeChangeAdd(v.Items, v.AfterId))
} else if v := r.GetRemove(); v != nil {
changes = append(changes, slice.MakeChangeRemove[*model.BlockContentDataviewRelation](v.Ids))
} else if v := r.GetMove(); v != nil {
changes = append(changes, slice.MakeChangeMove[*model.BlockContentDataviewRelation](v.Ids, v.AfterId))
}
}
view.Relations = slice.ApplyChanges(view.Relations, changes, getViewRelationID)
}
{
var changes []slice.Change[*model.BlockContentDataviewFilter]
for _, r := range upd.Filter {
if v := r.GetUpdate(); v != nil {
changes = append(changes, slice.MakeChangeReplace(v.Item, v.Id))
} else if v := r.GetAdd(); v != nil {
changes = append(changes, slice.MakeChangeAdd(v.Items, v.AfterId))
} else if v := r.GetRemove(); v != nil {
changes = append(changes, slice.MakeChangeRemove[*model.BlockContentDataviewFilter](v.Ids))
} else if v := r.GetMove(); v != nil {
changes = append(changes, slice.MakeChangeMove[*model.BlockContentDataviewFilter](v.Ids, v.AfterId))
}
}
view.Filters = slice.ApplyChanges(view.Filters, changes, getViewFilterID)
}
{
var changes []slice.Change[*model.BlockContentDataviewSort]
for _, r := range upd.Sort {
if v := r.GetUpdate(); v != nil {
changes = append(changes, slice.MakeChangeReplace(v.Item, v.Id))
} else if v := r.GetAdd(); v != nil {
changes = append(changes, slice.MakeChangeAdd(v.Items, v.AfterId))
} else if v := r.GetRemove(); v != nil {
changes = append(changes, slice.MakeChangeRemove[*model.BlockContentDataviewSort](v.Ids))
} else if v := r.GetMove(); v != nil {
changes = append(changes, slice.MakeChangeMove[*model.BlockContentDataviewSort](v.Ids, v.AfterId))
}
}
view.Sorts = slice.ApplyChanges(view.Sorts, changes, getViewSortID)
}
}
func unwrapChanges[T, R any](
changes []slice.Change[T],
add func(afterID string, items []T) R,
remove func(ids []string) R,
move func(afterID string, ids []string) R,
update func(id string, item T) R,
) []R {
res := make([]R, 0, len(changes))
for _, c := range changes {
if v := c.Add(); v != nil {
res = append(res, add(v.AfterID, v.Items))
}
if v := c.Remove(); v != nil {
res = append(res, remove(v.IDs))
}
if v := c.Move(); v != nil {
res = append(res, move(v.AfterID, v.IDs))
}
if v := c.Replace(); v != nil {
res = append(res, update(v.ID, v.Item))
}
}
return res
}
func diffViewObjectOrder(a, b *model.BlockContentDataviewObjectOrder) []*pb.EventBlockDataviewSliceChange {
diff := slice.Diff(a.ObjectIds, b.ObjectIds, slice.StringIdentity[string], slice.Equal[string])
if len(diff) == 0 {
return nil
}
var res []*pb.EventBlockDataviewSliceChange
for _, sliceCh := range diff {
if add := sliceCh.Add(); add != nil {
res = append(res, &pb.EventBlockDataviewSliceChange{
Op: pb.EventBlockDataview_SliceOperationAdd,
Ids: add.Items,
AfterId: add.AfterID,
})
}
if move := sliceCh.Move(); move != nil {
res = append(res, &pb.EventBlockDataviewSliceChange{
Op: pb.EventBlockDataview_SliceOperationMove,
Ids: move.IDs,
AfterId: move.AfterID,
})
}
if rm := sliceCh.Remove(); rm != nil {
res = append(res, &pb.EventBlockDataviewSliceChange{
Op: pb.EventBlockDataview_SliceOperationRemove,
Ids: rm.IDs,
})
}
// Replace change is not supported
}
return res
}
func (l *Dataview) ApplyObjectOrderUpdate(upd *pb.EventBlockDataviewObjectOrderUpdate) {
var existOrder []string
for _, order := range l.Model().GetDataview().ObjectOrders {
if order.ViewId == upd.ViewId && order.GroupId == upd.GroupId {
existOrder = order.ObjectIds
}
}
rawChanges := upd.GetSliceChanges()
changes := make([]slice.Change[string], 0, len(rawChanges))
for _, eventCh := range rawChanges {
var ch slice.Change[string]
switch eventCh.Op {
case pb.EventBlockDataview_SliceOperationAdd:
ch = slice.MakeChangeAdd(eventCh.Ids, eventCh.AfterId)
case pb.EventBlockDataview_SliceOperationMove:
ch = slice.MakeChangeMove[string](eventCh.Ids, eventCh.AfterId)
case pb.EventBlockDataview_SliceOperationRemove:
ch = slice.MakeChangeRemove[string](eventCh.Ids)
case pb.EventBlockDataview_SliceOperationReplace:
// Replace change is not supported
}
changes = append(changes, ch)
}
changedIds := slice.ApplyChanges(existOrder, changes, slice.StringIdentity[string])
l.SetViewObjectOrder([]*model.BlockContentDataviewObjectOrder{
{ViewId: upd.ViewId, GroupId: upd.GroupId, ObjectIds: changedIds},
})
}

View file

@ -0,0 +1,195 @@
package dataview
import (
"fmt"
"github.com/globalsign/mgo/bson"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/slice"
)
func (l *Dataview) AddFilter(viewID string, filter *model.BlockContentDataviewFilter) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
if filter.Id == "" {
filter.Id = bson.NewObjectId().Hex()
}
view.Filters = append(view.Filters, filter)
return nil
}
func (l *Dataview) RemoveFilters(viewID string, filterIDs []string) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
view.Filters = slice.Filter(view.Filters, func(f *model.BlockContentDataviewFilter) bool {
return slice.FindPos(filterIDs, f.Id) == -1
})
return nil
}
func (l *Dataview) ReplaceFilter(viewID string, filterID string, filter *model.BlockContentDataviewFilter) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
idx := slice.Find(view.Filters, func(f *model.BlockContentDataviewFilter) bool {
return f.Id == filterID
})
if idx < 0 {
return fmt.Errorf("filter with id %s is not found", filter.RelationKey)
}
filter.Id = filterID
view.Filters[idx] = filter
return nil
}
func (l *Dataview) ReorderFilters(viewID string, ids []string) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
filtersMap := make(map[string]*model.BlockContentDataviewFilter)
for _, f := range view.Filters {
filtersMap[f.Id] = f
}
view.Filters = view.Filters[:0]
for _, id := range ids {
if f, ok := filtersMap[id]; ok {
view.Filters = append(view.Filters, f)
}
}
return nil
}
func (l *Dataview) AddSort(viewID string, sort *model.BlockContentDataviewSort) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
view.Sorts = append(view.Sorts, sort)
return nil
}
func (l *Dataview) RemoveSorts(viewID string, relationKeys []string) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
view.Sorts = slice.Filter(view.Sorts, func(f *model.BlockContentDataviewSort) bool {
return slice.FindPos(relationKeys, getViewSortID(f)) == -1
})
return nil
}
func (l *Dataview) ReplaceSort(viewID string, relationKey string, sort *model.BlockContentDataviewSort) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
idx := slice.Find(view.Sorts, func(f *model.BlockContentDataviewSort) bool {
return getViewSortID(f) == relationKey
})
if idx < 0 {
return fmt.Errorf("sort with id %s is not found", sort.RelationKey)
}
view.Sorts[idx] = sort
return nil
}
func (l *Dataview) ReorderSorts(viewID string, relationKeys []string) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
sortsMap := make(map[string]*model.BlockContentDataviewSort)
for _, f := range view.Sorts {
sortsMap[getViewSortID(f)] = f
}
view.Sorts = view.Sorts[:0]
for _, id := range relationKeys {
if f, ok := sortsMap[id]; ok {
view.Sorts = append(view.Sorts, f)
}
}
return nil
}
func (l *Dataview) AddViewRelation(viewID string, relation *model.BlockContentDataviewRelation) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
view.Relations = append(view.Relations, relation)
return nil
}
func (l *Dataview) RemoveViewRelations(viewID string, relationKeys []string) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
view.Relations = slice.Filter(view.Relations, func(f *model.BlockContentDataviewRelation) bool {
return slice.FindPos(relationKeys, f.Key) == -1
})
return nil
}
func (l *Dataview) ReplaceViewRelation(viewID string, relationKey string, relation *model.BlockContentDataviewRelation) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
idx := slice.Find(view.Relations, func(f *model.BlockContentDataviewRelation) bool {
return f.Key == relationKey
})
if idx < 0 {
return fmt.Errorf("relation with key %s is not found", relationKey)
}
view.Relations[idx] = relation
return nil
}
func (l *Dataview) ReorderViewRelations(viewID string, relationKeys []string) error {
view, err := l.GetView(viewID)
if err != nil {
return err
}
relationsMap := make(map[string]*model.BlockContentDataviewRelation)
for _, r := range view.Relations {
relationsMap[r.Key] = r
}
view.Relations = view.Relations[:0]
for _, key := range relationKeys {
if r, ok := relationsMap[key]; ok {
view.Relations = append(view.Relations, r)
}
}
return nil
}

View file

@ -2,7 +2,6 @@ package core
import (
"context"
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
@ -72,6 +71,46 @@ func (mw *Middleware) BlockDataviewObjectOrderUpdate(cctx context.Context, req *
return response(pb.RpcBlockDataviewObjectOrderUpdateResponseError_NULL, nil)
}
func (mw *Middleware) BlockDataviewCreateFromExistingObject(cctx context.Context,
req *pb.RpcBlockDataviewCreateFromExistingObjectRequest) *pb.RpcBlockDataviewCreateFromExistingObjectResponse {
ctx := mw.newContext(cctx)
response := func(code pb.RpcBlockDataviewCreateFromExistingObjectResponseErrorCode,
blockId string,
targetObjectId string,
views []*model.BlockContentDataviewView,
err error) *pb.RpcBlockDataviewCreateFromExistingObjectResponse {
m := &pb.RpcBlockDataviewCreateFromExistingObjectResponse{
BlockId: blockId,
TargetObjectId: targetObjectId,
View: views,
Error: &pb.RpcBlockDataviewCreateFromExistingObjectResponseError{Code: code},
}
if err != nil {
m.Error.Description = err.Error()
} else {
m.Event = ctx.GetResponseEvent()
}
return m
}
var views []*model.BlockContentDataviewView
err := mw.doBlockService(func(bs *block.Service) error {
var err error
views, err = bs.CopyDataviewToBlock(ctx, req)
return err
})
if err != nil {
return response(pb.RpcBlockDataviewCreateFromExistingObjectResponseError_UNKNOWN_ERROR,
req.BlockId, req.TargetObjectId, views, err)
}
return response(pb.RpcBlockDataviewCreateFromExistingObjectResponseError_NULL,
req.BlockId, req.TargetObjectId, views, err)
}
func (mw *Middleware) BlockDataviewViewUpdate(cctx context.Context, req *pb.RpcBlockDataviewViewUpdateRequest) *pb.RpcBlockDataviewViewUpdateResponse {
ctx := mw.newContext(cctx)
response := func(code pb.RpcBlockDataviewViewUpdateResponseErrorCode, err error) *pb.RpcBlockDataviewViewUpdateResponse {
@ -239,3 +278,291 @@ func (mw *Middleware) BlockDataviewSetSource(cctx context.Context, req *pb.RpcBl
return resp(err)
}
func (mw *Middleware) BlockDataviewFilterAdd(cctx context.Context, req *pb.RpcBlockDataviewFilterAddRequest) *pb.RpcBlockDataviewFilterAddResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewFilterAddResponse {
r := &pb.RpcBlockDataviewFilterAddResponse{
Error: &pb.RpcBlockDataviewFilterAddResponseError{
Code: pb.RpcBlockDataviewFilterAddResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewFilterAddResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.AddDataviewFilter(ctx, req.ContextId, req.BlockId, req.ViewId, req.Filter)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewFilterRemove(cctx context.Context, req *pb.RpcBlockDataviewFilterRemoveRequest) *pb.RpcBlockDataviewFilterRemoveResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewFilterRemoveResponse {
r := &pb.RpcBlockDataviewFilterRemoveResponse{
Error: &pb.RpcBlockDataviewFilterRemoveResponseError{
Code: pb.RpcBlockDataviewFilterRemoveResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewFilterRemoveResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.RemoveDataviewFilters(ctx, req.ContextId, req.BlockId, req.ViewId, req.FilterIds)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewFilterReplace(cctx context.Context, req *pb.RpcBlockDataviewFilterReplaceRequest) *pb.RpcBlockDataviewFilterReplaceResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewFilterReplaceResponse {
r := &pb.RpcBlockDataviewFilterReplaceResponse{
Error: &pb.RpcBlockDataviewFilterReplaceResponseError{
Code: pb.RpcBlockDataviewFilterReplaceResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewFilterReplaceResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.ReplaceDataviewFilter(ctx, req.ContextId, req.BlockId, req.ViewId, req.FilterId, req.Filter)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewFilterSort(cctx context.Context, req *pb.RpcBlockDataviewFilterSortRequest) *pb.RpcBlockDataviewFilterSortResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewFilterSortResponse {
r := &pb.RpcBlockDataviewFilterSortResponse{
Error: &pb.RpcBlockDataviewFilterSortResponseError{
Code: pb.RpcBlockDataviewFilterSortResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewFilterSortResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.ReorderDataviewFilters(ctx, req.ContextId, req.BlockId, req.ViewId, req.FilterIds)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewSortAdd(cctx context.Context, req *pb.RpcBlockDataviewSortAddRequest) *pb.RpcBlockDataviewSortAddResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewSortAddResponse {
r := &pb.RpcBlockDataviewSortAddResponse{
Error: &pb.RpcBlockDataviewSortAddResponseError{
Code: pb.RpcBlockDataviewSortAddResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewSortAddResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.AddDataviewSort(ctx, req.ContextId, req.BlockId, req.ViewId, req.Sort)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewSortRemove(cctx context.Context, req *pb.RpcBlockDataviewSortRemoveRequest) *pb.RpcBlockDataviewSortRemoveResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewSortRemoveResponse {
r := &pb.RpcBlockDataviewSortRemoveResponse{
Error: &pb.RpcBlockDataviewSortRemoveResponseError{
Code: pb.RpcBlockDataviewSortRemoveResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewSortRemoveResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.RemoveDataviewSorts(ctx, req.ContextId, req.BlockId, req.ViewId, req.RelationKeys)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewSortReplace(cctx context.Context, req *pb.RpcBlockDataviewSortReplaceRequest) *pb.RpcBlockDataviewSortReplaceResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewSortReplaceResponse {
r := &pb.RpcBlockDataviewSortReplaceResponse{
Error: &pb.RpcBlockDataviewSortReplaceResponseError{
Code: pb.RpcBlockDataviewSortReplaceResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewSortReplaceResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.ReplaceDataviewSort(ctx, req.ContextId, req.BlockId, req.ViewId, req.RelationKey, req.Sort)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewSortSort(cctx context.Context, req *pb.RpcBlockDataviewSortSortRequest) *pb.RpcBlockDataviewSortSortResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewSortSortResponse {
r := &pb.RpcBlockDataviewSortSortResponse{
Error: &pb.RpcBlockDataviewSortSortResponseError{
Code: pb.RpcBlockDataviewSortSortResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewSortSortResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.ReorderDataviewSorts(ctx, req.ContextId, req.BlockId, req.ViewId, req.RelationKeys)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewViewRelationAdd(cctx context.Context, req *pb.RpcBlockDataviewViewRelationAddRequest) *pb.RpcBlockDataviewViewRelationAddResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewViewRelationAddResponse {
r := &pb.RpcBlockDataviewViewRelationAddResponse{
Error: &pb.RpcBlockDataviewViewRelationAddResponseError{
Code: pb.RpcBlockDataviewViewRelationAddResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewViewRelationAddResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.AddDataviewViewRelation(ctx, req.ContextId, req.BlockId, req.ViewId, req.Relation)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewViewRelationRemove(cctx context.Context, req *pb.RpcBlockDataviewViewRelationRemoveRequest) *pb.RpcBlockDataviewViewRelationRemoveResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewViewRelationRemoveResponse {
r := &pb.RpcBlockDataviewViewRelationRemoveResponse{
Error: &pb.RpcBlockDataviewViewRelationRemoveResponseError{
Code: pb.RpcBlockDataviewViewRelationRemoveResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewViewRelationRemoveResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.RemoveDataviewViewRelations(ctx, req.ContextId, req.BlockId, req.ViewId, req.RelationKeys)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewViewRelationReplace(cctx context.Context, req *pb.RpcBlockDataviewViewRelationReplaceRequest) *pb.RpcBlockDataviewViewRelationReplaceResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewViewRelationReplaceResponse {
r := &pb.RpcBlockDataviewViewRelationReplaceResponse{
Error: &pb.RpcBlockDataviewViewRelationReplaceResponseError{
Code: pb.RpcBlockDataviewViewRelationReplaceResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewViewRelationReplaceResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.ReplaceDataviewViewRelation(ctx, req.ContextId, req.BlockId, req.ViewId, req.RelationKey, req.Relation)
})
return resp(err)
}
func (mw *Middleware) BlockDataviewViewRelationSort(cctx context.Context, req *pb.RpcBlockDataviewViewRelationSortRequest) *pb.RpcBlockDataviewViewRelationSortResponse {
ctx := mw.newContext(cctx)
resp := func(err error) *pb.RpcBlockDataviewViewRelationSortResponse {
r := &pb.RpcBlockDataviewViewRelationSortResponse{
Error: &pb.RpcBlockDataviewViewRelationSortResponseError{
Code: pb.RpcBlockDataviewViewRelationSortResponseError_NULL,
},
}
if err != nil {
r.Error.Code = pb.RpcBlockDataviewViewRelationSortResponseError_UNKNOWN_ERROR
r.Error.Description = err.Error()
} else {
r.Event = ctx.GetResponseEvent()
}
return r
}
err := mw.doBlockService(func(bs *block.Service) error {
return bs.ReorderDataviewViewRelations(ctx, req.ContextId, req.BlockId, req.ViewId, req.RelationKeys)
})
return resp(err)
}

View file

@ -4,11 +4,13 @@ import (
"crypto/md5" //nolint:all
"encoding/hex"
"errors"
"fmt"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/database"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore/objectstore"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
)
import "github.com/anytypeio/go-anytype-middleware/app"
const (
CName = "kanban"
@ -52,7 +54,8 @@ func (s *service) Name() (name string) {
func (s *service) Grouper(key string) (Grouper, error) {
rel, err := s.objectStore.GetRelationByKey(key)
if err != nil {
return nil, err
return nil, fmt.Errorf("can't get relation %s: %v", key, err)
}
grouper, ok := s.groupColumns[rel.Format]

View file

@ -612,6 +612,27 @@ func (mw *Middleware) ObjectSetIsArchived(cctx context.Context, req *pb.RpcObjec
return response(pb.RpcObjectSetIsArchivedResponseError_NULL, nil)
}
func (mw *Middleware) ObjectSetSource(cctx context.Context,
req *pb.RpcObjectSetSourceRequest) *pb.RpcObjectSetSourceResponse {
ctx := mw.newContext(cctx)
response := func(code pb.RpcObjectSetSourceResponseErrorCode, err error) *pb.RpcObjectSetSourceResponse {
m := &pb.RpcObjectSetSourceResponse{Error: &pb.RpcObjectSetSourceResponseError{Code: code}}
if err != nil {
m.Error.Description = err.Error()
} else {
m.Event = ctx.GetResponseEvent()
}
return m
}
err := mw.doBlockService(func(bs *block.Service) (err error) {
return bs.SetSource(ctx, *req)
})
if err != nil {
return response(pb.RpcObjectSetSourceResponseError_UNKNOWN_ERROR, err)
}
return response(pb.RpcObjectSetSourceResponseError_NULL, nil)
}
func (mw *Middleware) ObjectSetIsFavorite(cctx context.Context, req *pb.RpcObjectSetIsFavoriteRequest) *pb.RpcObjectSetIsFavoriteResponse {
ctx := mw.newContext(cctx)
response := func(code pb.RpcObjectSetIsFavoriteResponseErrorCode, err error) *pb.RpcObjectSetIsFavoriteResponse {

View file

@ -55,7 +55,7 @@ func (r *Relation) ToStruct() *types.Struct {
bundle.RelationKeyName.String(): pbtypes.String(r.GetName()),
bundle.RelationKeyType.String(): pbtypes.String(bundle.TypeKeyRelation.URL()),
bundle.RelationKeyLayout.String(): pbtypes.Int64(int64(model.ObjectType_relation)),
bundle.RelationKeyRelationDefaultValue.String(): r.GetDefaultValue(),
bundle.RelationKeyRelationDefaultValue.String(): pbtypes.NilToNullWrapper(r.GetDefaultValue()),
bundle.RelationKeyIsHidden.String(): pbtypes.Bool(r.GetHidden()),
bundle.RelationKeyRelationReadonlyValue.String(): pbtypes.Bool(r.GetReadOnly()),
bundle.RelationKeyRelationFormatObjectTypes.String(): pbtypes.StringList(r.GetObjectTypes()),

File diff suppressed because it is too large Load diff

2
go.mod
View file

@ -317,3 +317,5 @@ replace gopkg.in/Graylog2/go-gelf.v2 => github.com/anytypeio/go-gelf v0.0.0-2021
replace github.com/araddon/dateparse => github.com/mehanizm/dateparse v0.0.0-20210806203422-f82c8742c9f8 // use a fork to support dd.mm.yyyy date format
replace github.com/multiformats/go-multiaddr => github.com/anytypeio/go-multiaddr v0.8.1-0.20221213144344-0b6b93adaec4
replace github.com/gogo/protobuf => github.com/anytypeio/protobuf v1.3.3-0.20230114170705-8e2cb769640b

13
go.sum
View file

@ -103,6 +103,8 @@ github.com/anytypeio/html-to-markdown v0.0.0-20200617145221-2afd2a14bae1 h1:g/LE
github.com/anytypeio/html-to-markdown v0.0.0-20200617145221-2afd2a14bae1/go.mod h1:Qnhxlb4mi8T2624UtHX8EgDyYZXWbjQfLGuciFHZ+Go=
github.com/anytypeio/ipfs-lite v1.4.3-0.20221213154513-adb3ebf9381c h1:1r6gf2nJaDw5eJA4k21Dqs4fCapImlHMNmOMv3livJA=
github.com/anytypeio/ipfs-lite v1.4.3-0.20221213154513-adb3ebf9381c/go.mod h1:4urJUIk36yaTHlgPuZ/YHUmtvAII19xVHmCE8YA7u54=
github.com/anytypeio/protobuf v1.3.3-0.20230114170705-8e2cb769640b h1:tcqOV1tvh8i76MpK6r0yaob4lkCdia69+gSi5SVz19c=
github.com/anytypeio/protobuf v1.3.3-0.20230114170705-8e2cb769640b/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@ -395,13 +397,6 @@ github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q8
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/googleapis v1.3.1 h1:CzMaKrvF6Qa7XtRii064vKBQiyvmY8H8vG1xa1/W1JA=
github.com/gogo/googleapis v1.3.1/go.mod h1:d+q1s/xVJxZGKWwC/6UfPIF33J+G1Tq4GYv9Y+Tg/EU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg=
github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU=
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
@ -783,8 +778,6 @@ github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
@ -1816,12 +1809,10 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1419,6 +1419,30 @@ message Rpc {
}
}
message SetSource {
message Request {
string contextId = 1;
repeated string source = 2;
}
message Response {
Error error = 1;
ResponseEvent event = 4;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message SetObjectType {
message Request {
string contextId = 1;
@ -4224,6 +4248,7 @@ message Rpc {
string contextId = 1;
string blockId = 2; // id of dataview block to insert the new block
anytype.model.Block.Content.Dataview.View view = 4;
repeated string source = 5;
}
message Response {
@ -4491,6 +4516,34 @@ message Rpc {
}
}
message CreateFromExistingObject {
message Request {
string contextId = 1;
string blockId = 2;
string targetObjectId = 3;
}
message Response {
Error error = 1;
string blockId = 2;
string targetObjectId = 3;
repeated anytype.model.Block.Content.Dataview.View view = 4;
ResponseEvent event = 5;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
// ...
}
}
}
}
message CreateBookmark {
message Request {
string contextId = 1;
@ -4514,6 +4567,313 @@ message Rpc {
}
}
}
message Filter {
message Add {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
anytype.model.Block.Content.Dataview.Filter filter = 4;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Remove {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
repeated string filterIds = 4;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Replace {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
string filterId = 4;
anytype.model.Block.Content.Dataview.Filter filter = 5;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Sort {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
repeated string filterIds = 4; // new order of filters
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
}
message Sort {
message Add {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
anytype.model.Block.Content.Dataview.Sort sort = 4;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Remove {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
repeated string relationKeys = 4;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Replace {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
string relationKey = 4;
anytype.model.Block.Content.Dataview.Sort sort = 5;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Sort {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
repeated string relationKeys = 4; // new order of sorts
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
}
message ViewRelation {
message Add {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
anytype.model.Block.Content.Dataview.Relation relation = 4;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Remove {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
repeated string relationKeys = 4;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Replace {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
string relationKey = 4;
anytype.model.Block.Content.Dataview.Relation relation = 5;
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
message Sort {
message Request {
string contextId = 1;
string blockId = 2; // id of dataview block to update
string viewId = 3; // id of view to update
repeated string relationKeys = 4; // new order of relations
}
message Response {
Error error = 1;
ResponseEvent event = 2;
message Error {
Code code = 1;
string description = 2;
enum Code {
NULL = 0;
UNKNOWN_ERROR = 1;
BAD_INPUT = 2;
}
}
}
}
}
}
message Debug {

View file

@ -65,6 +65,8 @@ message Event {
Block.Dataview.ObjectOrderUpdate blockDataViewObjectOrderUpdate = 39;
Block.Dataview.RelationDelete blockDataviewRelationDelete = 124;
Block.Dataview.RelationSet blockDataviewRelationSet = 123;
Block.Dataview.ViewUpdate blockDataviewViewUpdate = 125;
Block.Dataview.TargetObjectIdSet blockDataviewTargetObjectIdSet = 126;
// deprecated
Block.Dataview.OldRelationDelete blockDataviewOldRelationDelete = 24;
@ -682,6 +684,102 @@ message Event {
anytype.model.Block.Content.Dataview.View view = 3;
}
message ViewUpdate {
string id = 1;
string viewId = 2;
repeated Filter filter = 3;
repeated Relation relation = 4;
repeated Sort sort = 5;
Fields fields = 6;
message Fields {
anytype.model.Block.Content.Dataview.View.Type type = 1;
string name = 2;
string coverRelationKey = 3; // Relation used for cover in gallery
bool hideIcon = 4; // Hide icon near name
anytype.model.Block.Content.Dataview.View.Size cardSize = 5; // Gallery card size
bool coverFit = 6; // Image fits container
string groupRelationKey = 7; // Group view by this relationKey
bool groupBackgroundColors = 8; // Enable backgrounds in groups
int32 pageLimit = 9;
}
message Filter {
oneof operation {
Add add = 1;
Remove remove = 2;
Update update = 3;
Move move = 4;
}
message Add {
string afterId = 1;
repeated anytype.model.Block.Content.Dataview.Filter items = 2;
}
message Remove {
repeated string ids = 1;
}
message Update {
string id = 1;
anytype.model.Block.Content.Dataview.Filter item = 2;
}
message Move {
string afterId = 1;
repeated string ids = 2;
}
}
message Relation {
oneof operation {
Add add = 1;
Remove remove = 2;
Update update = 3;
Move move = 4;
}
message Add {
string afterId = 1;
repeated anytype.model.Block.Content.Dataview.Relation items = 2;
}
message Remove {
repeated string ids = 1;
}
message Update {
string id = 1;
anytype.model.Block.Content.Dataview.Relation item = 2;
}
message Move {
string afterId = 1;
repeated string ids = 2;
}
}
message Sort {
oneof operation {
Add add = 1;
Remove remove = 2;
Update update = 3;
Move move = 4;
}
message Add {
string afterId = 1;
repeated anytype.model.Block.Content.Dataview.Sort items = 2;
}
message Remove {
repeated string ids = 1;
}
message Update {
string id = 1;
anytype.model.Block.Content.Dataview.Sort item = 2;
}
message Move {
string afterId = 1;
repeated string ids = 2;
}
}
}
message ViewDelete {
string id = 1; // dataview block's id
string viewId = 2; // view id to remove
@ -746,6 +844,11 @@ message Event {
SliceOperationRemove = 3;
SliceOperationReplace = 4;
}
message TargetObjectIdSet {
string id = 1; // dataview block's id
string targetObjectId = 2;
}
}
}

View file

@ -64,6 +64,7 @@ service ClientCommands {
rpc ObjectSetInternalFlags (anytype.Rpc.Object.SetInternalFlags.Request) returns (anytype.Rpc.Object.SetInternalFlags.Response);
rpc ObjectSetIsFavorite (anytype.Rpc.Object.SetIsFavorite.Request) returns (anytype.Rpc.Object.SetIsFavorite.Response);
rpc ObjectSetIsArchived (anytype.Rpc.Object.SetIsArchived.Request) returns (anytype.Rpc.Object.SetIsArchived.Response);
rpc ObjectSetSource (anytype.Rpc.Object.SetSource.Request) returns (anytype.Rpc.Object.SetSource.Response);
rpc ObjectListDuplicate (anytype.Rpc.Object.ListDuplicate.Request) returns (anytype.Rpc.Object.ListDuplicate.Response);
rpc ObjectListDelete (anytype.Rpc.Object.ListDelete.Request) returns (anytype.Rpc.Object.ListDelete.Response);
rpc ObjectListSetIsArchived (anytype.Rpc.Object.ListSetIsArchived.Request) returns (anytype.Rpc.Object.ListSetIsArchived.Response);
@ -191,6 +192,22 @@ service ClientCommands {
rpc BlockDataviewRelationListAvailable (anytype.Rpc.BlockDataview.Relation.ListAvailable.Request) returns (anytype.Rpc.BlockDataview.Relation.ListAvailable.Response);
rpc BlockDataviewGroupOrderUpdate (anytype.Rpc.BlockDataview.GroupOrder.Update.Request) returns (anytype.Rpc.BlockDataview.GroupOrder.Update.Response);
rpc BlockDataviewObjectOrderUpdate (anytype.Rpc.BlockDataview.ObjectOrder.Update.Request) returns (anytype.Rpc.BlockDataview.ObjectOrder.Update.Response);
rpc BlockDataviewCreateFromExistingObject (anytype.Rpc.BlockDataview.CreateFromExistingObject.Request) returns (anytype.Rpc.BlockDataview.CreateFromExistingObject.Response);
rpc BlockDataviewFilterAdd (anytype.Rpc.BlockDataview.Filter.Add.Request) returns (anytype.Rpc.BlockDataview.Filter.Add.Response);
rpc BlockDataviewFilterRemove (anytype.Rpc.BlockDataview.Filter.Remove.Request) returns (anytype.Rpc.BlockDataview.Filter.Remove.Response);
rpc BlockDataviewFilterReplace (anytype.Rpc.BlockDataview.Filter.Replace.Request) returns (anytype.Rpc.BlockDataview.Filter.Replace.Response);
rpc BlockDataviewFilterSort (anytype.Rpc.BlockDataview.Filter.Sort.Request) returns (anytype.Rpc.BlockDataview.Filter.Sort.Response);
rpc BlockDataviewSortAdd (anytype.Rpc.BlockDataview.Sort.Add.Request) returns (anytype.Rpc.BlockDataview.Sort.Add.Response);
rpc BlockDataviewSortRemove (anytype.Rpc.BlockDataview.Sort.Remove.Request) returns (anytype.Rpc.BlockDataview.Sort.Remove.Response);
rpc BlockDataviewSortReplace (anytype.Rpc.BlockDataview.Sort.Replace.Request) returns (anytype.Rpc.BlockDataview.Sort.Replace.Response);
rpc BlockDataviewSortSort (anytype.Rpc.BlockDataview.Sort.Sort.Request) returns (anytype.Rpc.BlockDataview.Sort.Sort.Response);
rpc BlockDataviewViewRelationAdd (anytype.Rpc.BlockDataview.ViewRelation.Add.Request) returns (anytype.Rpc.BlockDataview.ViewRelation.Add.Response);
rpc BlockDataviewViewRelationRemove (anytype.Rpc.BlockDataview.ViewRelation.Remove.Request) returns (anytype.Rpc.BlockDataview.ViewRelation.Remove.Response);
rpc BlockDataviewViewRelationReplace (anytype.Rpc.BlockDataview.ViewRelation.Replace.Request) returns (anytype.Rpc.BlockDataview.ViewRelation.Replace.Response);
rpc BlockDataviewViewRelationSort (anytype.Rpc.BlockDataview.ViewRelation.Sort.Request) returns (anytype.Rpc.BlockDataview.ViewRelation.Sort.Response);
// Simple table block commands
// ***

File diff suppressed because it is too large Load diff

View file

@ -4,10 +4,11 @@ import (
"fmt"
"strings"
types2 "github.com/gogo/protobuf/types"
coresb "github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore/addr"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
types2 "github.com/gogo/protobuf/types"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
)
@ -59,6 +60,7 @@ var SystemRelations = append(RequiredInternalRelations, []RelationKey{
RelationKeyIsReadonly,
RelationKeyIsDeleted,
RelationKeyIsHidden,
RelationKeyDone,
RelationKeyIsArchived,
RelationKeyTemplateIsBundled,
RelationKeyTag,

View file

@ -6,7 +6,7 @@ package bundle
import "github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
const RelationChecksum = "f5c7d5db3c6f88a59fe345425922e9e5898f4557d2cbb454e4c2e1eb5d7a120b"
const RelationChecksum = "47980e2ed93f7ed22d3c6f22facaf03a60bc1f5aa7fbe959baf94ee4509dadc7"
type RelationKey string
@ -1921,7 +1921,7 @@ var (
},
RelationKeySetOf: {
DataSource: model.Relation_derived,
DataSource: model.Relation_details,
Description: "Point to the object types or realtions used to aggregate the set. Empty means object of all types will be aggregated ",
Format: model.RelationFormat_object,
Id: "_brsetOf",

View file

@ -1521,7 +1521,7 @@
"objectType"
],
"readonly": true,
"source": "derived"
"source": "details"
},
{
"format": "status",

View file

@ -206,6 +206,8 @@ func NewFilters(q Query, sch schema.Schema, loc *time.Location) (f *Filters, err
Key: s.RelationKey,
Type: s.Type,
EmptyLast: emptyLast,
IncludeTime: s.IncludeTime,
RelationFormat: s.Format,
}
if s.Type == model.BlockContentDataviewSort_Custom && len(s.CustomOrder) > 0 {

View file

@ -5,13 +5,14 @@ import (
"fmt"
"strings"
"github.com/gogo/protobuf/types"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
"github.com/gogo/protobuf/types"
)
var (
ErrValueMustBeList = errors.New("value must be list")
ErrValueMustBeListSupporting = errors.New("value must be list supporting")
)
func MakeAndFilter(protoFilters []*model.BlockContentDataviewFilter) (Filter, error) {
@ -78,18 +79,18 @@ func MakeFilter(proto *model.BlockContentDataviewFilter) (Filter, error) {
Value: proto.Value,
}}, nil
case model.BlockContentDataviewFilter_In:
list := proto.Value.GetListValue()
if list == nil {
return nil, ErrValueMustBeList
list, err := pbtypes.ValueListWrapper(proto.Value)
if err != nil {
return nil, ErrValueMustBeListSupporting
}
return In{
Key: proto.RelationKey,
Value: list,
}, nil
case model.BlockContentDataviewFilter_NotIn:
list := proto.Value.GetListValue()
if list == nil {
return nil, ErrValueMustBeList
list, err := pbtypes.ValueListWrapper(proto.Value)
if err != nil {
return nil, ErrValueMustBeListSupporting
}
return Not{In{
Key: proto.RelationKey,
@ -104,36 +105,36 @@ func MakeFilter(proto *model.BlockContentDataviewFilter) (Filter, error) {
Key: proto.RelationKey,
}}, nil
case model.BlockContentDataviewFilter_AllIn:
list := proto.Value.GetListValue()
if list == nil {
return nil, ErrValueMustBeList
list, err := pbtypes.ValueListWrapper(proto.Value)
if err != nil {
return nil, ErrValueMustBeListSupporting
}
return AllIn{
Key: proto.RelationKey,
Value: list,
}, nil
case model.BlockContentDataviewFilter_NotAllIn:
list := proto.Value.GetListValue()
if list == nil {
return nil, ErrValueMustBeList
list, err := pbtypes.ValueListWrapper(proto.Value)
if err != nil {
return nil, ErrValueMustBeListSupporting
}
return Not{AllIn{
Key: proto.RelationKey,
Value: list,
}}, nil
case model.BlockContentDataviewFilter_ExactIn:
list := proto.Value.GetListValue()
if list == nil {
return nil, ErrValueMustBeList
list, err := pbtypes.ValueListWrapper(proto.Value)
if err != nil {
return nil, ErrValueMustBeListSupporting
}
return ExactIn{
Key: proto.RelationKey,
Value: list,
}, nil
case model.BlockContentDataviewFilter_NotExactIn:
list := proto.Value.GetListValue()
if list == nil {
return nil, ErrValueMustBeList
list, err := pbtypes.ValueListWrapper(proto.Value)
if err != nil {
return nil, ErrValueMustBeListSupporting
}
return Not{ExactIn{
Key: proto.RelationKey,
@ -362,12 +363,16 @@ func (l AllIn) FilterObject(g Getter) bool {
if val == nil {
return false
}
list := val.GetListValue()
list, err := pbtypes.ValueListWrapper(val)
if err != nil {
return false
}
if list == nil {
return false
}
exist := func(v *types.Value) bool {
for _, lv := range list.Values {
for _, lv := range list.GetValues() {
if v.Equal(lv) {
return true
}
@ -396,7 +401,10 @@ func (exIn ExactIn) FilterObject(g Getter) bool {
if val == nil {
return false
}
list := val.GetListValue()
list, err := pbtypes.ValueListWrapper(val)
if err != nil {
return false
}
if list == nil {
return false
}

View file

@ -3,11 +3,12 @@ package filter
import (
"testing"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
"github.com/gogo/protobuf/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
)
type testGetter map[string]*types.Value
@ -227,6 +228,22 @@ func TestAllIn_FilterObject(t *testing.T) {
g := testGetter{"k": pbtypes.StringList([]string{"2", "3", "4"})}
assert.False(t, allIn.FilterObject(g))
})
t.Run("ok string in Object", func(t *testing.T) {
allIn := AllIn{Key: "k", Value: pbtypes.StringList([]string{"1"}).GetListValue()}
g := testGetter{"k": pbtypes.String("1")}
assert.True(t, allIn.FilterObject(g))
})
t.Run("ok string in Filter", func(t *testing.T) {
v, err := pbtypes.ValueListWrapper(pbtypes.String("1"))
assert.NoError(t, err)
allIn := AllIn{Key: "k", Value: v}
g := testGetter{"k": pbtypes.StringList([]string{"1", "2", "3"})}
assert.True(t, allIn.FilterObject(g))
})
}
func TestMakeAndFilter(t *testing.T) {
@ -313,9 +330,9 @@ func TestMakeAndFilter(t *testing.T) {
model.BlockContentDataviewFilter_NotAllIn,
} {
_, err := MakeAndFilter([]*model.BlockContentDataviewFilter{
{Condition: cond, Value: pbtypes.String("not list")},
{Condition: cond, Value: pbtypes.Null()},
})
assert.Equal(t, ErrValueMustBeList, err)
assert.Equal(t, ErrValueMustBeListSupporting, err)
}
})

View file

@ -1,10 +1,10 @@
package filter
import (
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
time_util "github.com/anytypeio/go-anytype-middleware/util/time"
"github.com/gogo/protobuf/types"
"strings"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
)
type Order interface {
@ -32,14 +32,22 @@ func (so SetOrder) String() (s string) {
}
type KeyOrder struct {
Key string
Type model.BlockContentDataviewSortType
EmptyLast bool // consider empty strings as the last, not first
Key string
Type model.BlockContentDataviewSortType
EmptyLast bool // consider empty strings as the last, not first
RelationFormat model.RelationFormat
IncludeTime bool
}
func (ko KeyOrder) Compare(a, b Getter) int {
av := a.Get(ko.Key)
bv := b.Get(ko.Key)
if ko.RelationFormat == model.RelationFormat_date && !ko.IncludeTime {
av = time_util.CutValueToDay(av)
bv = time_util.CutValueToDay(bv)
}
comp := 0
_, aString := av.GetKind().(*types.Value_StringValue)
_, bString := bv.GetKind().(*types.Value_StringValue)

View file

@ -3,6 +3,7 @@ package filter
import (
"github.com/gogo/protobuf/types"
"testing"
"time"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
@ -137,4 +138,41 @@ func TestCustomOrder_Compare(t *testing.T) {
b := testGetter{"ID": pbtypes.String("y")}
assert.Equal(t, 1, co.Compare(a, b))
})
}
}
func TestIncludeTime_Compare(t *testing.T) {
date := time.Unix(1672012800, 0)
t.Run("date only eq", func(t *testing.T) {
a := testGetter{"k": pbtypes.Int64(date.Add(time.Second * 5).Unix())}
b := testGetter{"k": pbtypes.Int64(date.Add(time.Second * 10).Unix())}
asc := KeyOrder{Key: "k", Type: model.BlockContentDataviewSort_Asc,
IncludeTime: false, RelationFormat: model.RelationFormat_date}
assert.Equal(t, 0, asc.Compare(a, b))
})
t.Run("only date lt", func(t *testing.T) {
a := testGetter{"k": pbtypes.Int64(date.Unix())}
b := testGetter{"k": pbtypes.Int64(date.Add(time.Hour * 24).Unix())}
asc := KeyOrder{Key: "k", Type: model.BlockContentDataviewSort_Asc,
IncludeTime: false, RelationFormat: model.RelationFormat_date}
assert.Equal(t, -1, asc.Compare(a, b))
})
t.Run("date includeTime eq", func(t *testing.T) {
a := testGetter{"k": pbtypes.Int64(date.Add(time.Second * 10).Unix())}
b := testGetter{"k": pbtypes.Int64(date.Add(time.Second * 10).Unix())}
asc := KeyOrder{Key: "k", Type: model.BlockContentDataviewSort_Asc,
IncludeTime: true, RelationFormat: model.RelationFormat_date}
assert.Equal(t, 0, asc.Compare(a, b))
})
t.Run("date includeTime lt", func(t *testing.T) {
a := testGetter{"k": pbtypes.Int64(date.Add(time.Second * 5).Unix())}
b := testGetter{"k": pbtypes.Int64(date.Add(time.Second * 10).Unix())}
asc := KeyOrder{Key: "k", Type: model.BlockContentDataviewSort_Asc,
IncludeTime: true, RelationFormat: model.RelationFormat_date}
assert.Equal(t, -1, asc.Compare(a, b))
})
}

View file

@ -4,13 +4,14 @@ import (
"context"
"encoding/binary"
"fmt"
"github.com/anytypeio/go-anytype-middleware/core/relation/relationutils"
"runtime/debug"
"strings"
"sync"
"time"
noctxds "github.com/anytypeio/go-anytype-middleware/pkg/lib/datastore/noctxds"
"github.com/anytypeio/go-anytype-middleware/core/relation/relationutils"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/datastore/noctxds"
"github.com/gogo/protobuf/proto"
"github.com/gogo/protobuf/types"
@ -1903,17 +1904,6 @@ func (m *dsObjectStore) updateDetails(txn noctxds.Txn, id string, oldDetails *mo
return nil
}
for k, v := range newDetails.GetDetails().GetFields() {
// todo: remove null cleanup(should be done when receiving from client)
if _, isNull := v.GetKind().(*types.Value_NullValue); v == nil || isNull {
if slice.FindPos(bundle.LocalRelationsKeys, k) > -1 || slice.FindPos(bundle.DerivedRelationsKeys, k) > -1 {
log.Errorf("updateDetails %s: localDetail nulled %s: %s", id, k, pbtypes.Sprint(v))
} else {
log.Warnf("updateDetails %s: detail nulled %s: %s", id, k, pbtypes.Sprint(v))
}
}
}
diff := pbtypes.StructDiff(oldDetails.GetDetails(), newDetails.GetDetails())
log.Debugf("updateDetails %s: diff %s", id, pbtypes.Sprint(diff))
err = localstore.UpdateIndexesWithTxn(m, txn, oldDetails, newDetails, id)

View file

@ -187,7 +187,7 @@ func (m *ImageResize) resizeJPEG(imgConfig *image.Config, r io.ReadSeeker) (*Res
width, height = resized.Rect.Max.X, resized.Rect.Max.Y
buff := &bytes.Buffer{}
if jpeg.Encode(buff, resized, &jpeg.Options{Quality: quality}) != nil {
if err = jpeg.Encode(buff, resized, &jpeg.Options{Quality: quality}); err != nil {
return nil, err
}
@ -233,7 +233,7 @@ func (m *ImageResize) resizePNG(imgConfig *image.Config, r io.ReadSeeker) (*Resu
width, height = resized.Rect.Max.X, resized.Rect.Max.Y
buff := &bytes.Buffer{}
if png.Encode(buff, resized) != nil {
if err = png.Encode(buff, resized); err != nil {
return nil, err
}
@ -285,7 +285,7 @@ func (m *ImageResize) resizeGIF(imgConfig *image.Config, r io.ReadSeeker) (*Resu
gifImg.Config.Width, gifImg.Config.Height = gifImg.Image[0].Bounds().Dx(), gifImg.Image[0].Bounds().Dy()
buff := bytes.NewBuffer(make([]byte, 0))
if gif.EncodeAll(buff, gifImg) != nil {
if err = gif.EncodeAll(buff, gifImg); err != nil {
return nil, err
}

View file

@ -2581,11 +2581,12 @@ type BlockContentDataview struct {
Source []string `protobuf:"bytes,1,rep,name=source,proto3" json:"source,omitempty"`
Views []*BlockContentDataviewView `protobuf:"bytes,2,rep,name=views,proto3" json:"views,omitempty"`
// deprecated
Relations []*Relation `protobuf:"bytes,4,rep,name=relations,proto3" json:"relations,omitempty"`
ActiveView string `protobuf:"bytes,3,opt,name=activeView,proto3" json:"activeView,omitempty"`
GroupOrders []*BlockContentDataviewGroupOrder `protobuf:"bytes,12,rep,name=groupOrders,proto3" json:"groupOrders,omitempty"`
ObjectOrders []*BlockContentDataviewObjectOrder `protobuf:"bytes,13,rep,name=objectOrders,proto3" json:"objectOrders,omitempty"`
RelationLinks []*RelationLink `protobuf:"bytes,5,rep,name=relationLinks,proto3" json:"relationLinks,omitempty"`
Relations []*Relation `protobuf:"bytes,4,rep,name=relations,proto3" json:"relations,omitempty"`
ActiveView string `protobuf:"bytes,3,opt,name=activeView,proto3" json:"activeView,omitempty"`
GroupOrders []*BlockContentDataviewGroupOrder `protobuf:"bytes,12,rep,name=groupOrders,proto3" json:"groupOrders,omitempty"`
ObjectOrders []*BlockContentDataviewObjectOrder `protobuf:"bytes,13,rep,name=objectOrders,proto3" json:"objectOrders,omitempty"`
RelationLinks []*RelationLink `protobuf:"bytes,5,rep,name=relationLinks,proto3" json:"relationLinks,omitempty"`
TargetObjectId string `protobuf:"bytes,6,opt,name=TargetObjectId,proto3" json:"TargetObjectId,omitempty"`
}
func (m *BlockContentDataview) Reset() { *m = BlockContentDataview{} }
@ -2670,6 +2671,13 @@ func (m *BlockContentDataview) GetRelationLinks() []*RelationLink {
return nil
}
func (m *BlockContentDataview) GetTargetObjectId() string {
if m != nil {
return m.TargetObjectId
}
return ""
}
type BlockContentDataviewView struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Type BlockContentDataviewViewType `protobuf:"varint,2,opt,name=type,proto3,enum=anytype.model.BlockContentDataviewViewType" json:"type,omitempty"`
@ -2683,6 +2691,7 @@ type BlockContentDataviewView struct {
CoverFit bool `protobuf:"varint,10,opt,name=coverFit,proto3" json:"coverFit,omitempty"`
GroupRelationKey string `protobuf:"bytes,11,opt,name=groupRelationKey,proto3" json:"groupRelationKey,omitempty"`
GroupBackgroundColors bool `protobuf:"varint,12,opt,name=groupBackgroundColors,proto3" json:"groupBackgroundColors,omitempty"`
PageLimit int32 `protobuf:"varint,13,opt,name=pageLimit,proto3" json:"pageLimit,omitempty"`
}
func (m *BlockContentDataviewView) Reset() { *m = BlockContentDataviewView{} }
@ -2802,6 +2811,13 @@ func (m *BlockContentDataviewView) GetGroupBackgroundColors() bool {
return false
}
func (m *BlockContentDataviewView) GetPageLimit() int32 {
if m != nil {
return m.PageLimit
}
return 0
}
type BlockContentDataviewRelation struct {
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
IsVisible bool `protobuf:"varint,2,opt,name=isVisible,proto3" json:"isVisible,omitempty"`
@ -2890,6 +2906,8 @@ type BlockContentDataviewSort struct {
RelationKey string `protobuf:"bytes,1,opt,name=RelationKey,proto3" json:"RelationKey,omitempty"`
Type BlockContentDataviewSortType `protobuf:"varint,2,opt,name=type,proto3,enum=anytype.model.BlockContentDataviewSortType" json:"type,omitempty"`
CustomOrder []*types.Value `protobuf:"bytes,3,rep,name=customOrder,proto3" json:"customOrder,omitempty"`
Format RelationFormat `protobuf:"varint,4,opt,name=format,proto3,enum=anytype.model.RelationFormat" json:"format,omitempty"`
IncludeTime bool `protobuf:"varint,5,opt,name=includeTime,proto3" json:"includeTime,omitempty"`
}
func (m *BlockContentDataviewSort) Reset() { *m = BlockContentDataviewSort{} }
@ -2946,7 +2964,22 @@ func (m *BlockContentDataviewSort) GetCustomOrder() []*types.Value {
return nil
}
func (m *BlockContentDataviewSort) GetFormat() RelationFormat {
if m != nil {
return m.Format
}
return RelationFormat_longtext
}
func (m *BlockContentDataviewSort) GetIncludeTime() bool {
if m != nil {
return m.IncludeTime
}
return false
}
type BlockContentDataviewFilter struct {
Id string `protobuf:"bytes,9,opt,name=id,proto3" json:"id,omitempty"`
Operator BlockContentDataviewFilterOperator `protobuf:"varint,1,opt,name=operator,proto3,enum=anytype.model.BlockContentDataviewFilterOperator" json:"operator,omitempty"`
RelationKey string `protobuf:"bytes,2,opt,name=RelationKey,proto3" json:"RelationKey,omitempty"`
RelationProperty string `protobuf:"bytes,5,opt,name=relationProperty,proto3" json:"relationProperty,omitempty"`
@ -2990,6 +3023,13 @@ func (m *BlockContentDataviewFilter) XXX_DiscardUnknown() {
var xxx_messageInfo_BlockContentDataviewFilter proto.InternalMessageInfo
func (m *BlockContentDataviewFilter) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *BlockContentDataviewFilter) GetOperator() BlockContentDataviewFilterOperator {
if m != nil {
return m.Operator
@ -5665,329 +5705,331 @@ func init() {
}
var fileDescriptor_98a910b73321e591 = []byte{
// 5142 bytes of a gzipped FileDescriptorProto
// 5182 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x3b, 0x4b, 0x8c, 0x1c, 0x49,
0x56, 0xf5, 0xff, 0xbc, 0xea, 0x6e, 0x47, 0x87, 0xdb, 0x76, 0x91, 0xf6, 0x1a, 0x6f, 0x32, 0xeb,
0xf5, 0x7a, 0x67, 0xdb, 0xe3, 0xdf, 0xce, 0xec, 0xc2, 0x8c, 0xdd, 0x1f, 0x7b, 0xbb, 0xe5, 0x4f,
0xf7, 0x64, 0xb5, 0x6d, 0x76, 0x04, 0x68, 0xb3, 0x2a, 0xa3, 0xab, 0x72, 0x3a, 0x2b, 0xa3, 0x26,
0x33, 0xaa, 0xdd, 0xbd, 0x12, 0xd2, 0xf2, 0x59, 0xce, 0xc3, 0x22, 0x04, 0x17, 0xa4, 0x45, 0x5c,
0xb9, 0x21, 0xc4, 0x47, 0x88, 0x1b, 0x12, 0x12, 0x12, 0x0c, 0xe2, 0x82, 0x84, 0x04, 0x68, 0xe6,
0xc8, 0x8d, 0x33, 0x42, 0xe8, 0xbd, 0x88, 0xcc, 0xca, 0xfa, 0x74, 0xbb, 0x7a, 0xd8, 0x53, 0xe5,
0x7b, 0xf1, 0xde, 0x8b, 0xdf, 0x8b, 0xf7, 0x8b, 0x28, 0x78, 0x6b, 0x70, 0xd0, 0xbd, 0x15, 0xf8,
0xed, 0x5b, 0x83, 0xf6, 0xad, 0xbe, 0xf4, 0x44, 0x70, 0x6b, 0x10, 0x49, 0x25, 0x63, 0x0d, 0xc4,
0xab, 0x04, 0xf1, 0x45, 0x37, 0x3c, 0x56, 0xc7, 0x03, 0xb1, 0x4a, 0x58, 0xeb, 0x4a, 0x57, 0xca,
0x6e, 0x20, 0x34, 0x69, 0x7b, 0xb8, 0x7f, 0x2b, 0x56, 0xd1, 0xb0, 0xa3, 0x34, 0xb1, 0xfd, 0x77,
0x45, 0xb8, 0xd8, 0xea, 0xbb, 0x91, 0x5a, 0x0f, 0x64, 0xe7, 0xa0, 0x15, 0xba, 0x83, 0xb8, 0x27,
0xd5, 0xba, 0x1b, 0x0b, 0xfe, 0x36, 0x54, 0xda, 0x88, 0x8c, 0x9b, 0xf9, 0x6b, 0xc5, 0x1b, 0x8d,
0x3b, 0x2b, 0xab, 0x63, 0x82, 0x57, 0x89, 0xc3, 0x31, 0x34, 0xfc, 0x36, 0x54, 0x3d, 0xa1, 0x5c,
0x3f, 0x88, 0x9b, 0x85, 0x6b, 0xf9, 0x1b, 0x8d, 0x3b, 0x97, 0x56, 0x75, 0xc7, 0xab, 0x49, 0xc7,
0xab, 0x2d, 0xea, 0xd8, 0x49, 0xe8, 0xf8, 0x5d, 0xa8, 0xed, 0xfb, 0x81, 0x78, 0x22, 0x8e, 0xe3,
0x66, 0xf1, 0x74, 0x9e, 0x94, 0x90, 0x3f, 0x80, 0x25, 0x71, 0xa4, 0x22, 0xd7, 0x11, 0x81, 0xab,
0x7c, 0x19, 0xc6, 0xcd, 0x12, 0x8d, 0xee, 0xd2, 0xc4, 0xe8, 0x92, 0x76, 0x67, 0x82, 0x9c, 0x5f,
0x83, 0x86, 0x6c, 0x7f, 0x2c, 0x3a, 0x6a, 0xef, 0x78, 0x20, 0xe2, 0x66, 0xf9, 0x5a, 0xf1, 0x46,
0xdd, 0xc9, 0xa2, 0xf8, 0x77, 0xa0, 0xd1, 0x91, 0x41, 0x20, 0x3a, 0x5a, 0x7e, 0xe5, 0xf4, 0xa1,
0x65, 0x69, 0xf9, 0x3d, 0xb8, 0x10, 0x89, 0xbe, 0x3c, 0x14, 0xde, 0x46, 0x8a, 0xa5, 0xf9, 0xd5,
0xa8, 0x9b, 0xd9, 0x8d, 0x7c, 0x0d, 0x16, 0x23, 0x33, 0xbe, 0xa7, 0x7e, 0x78, 0x10, 0x37, 0xab,
0x34, 0xa5, 0xcb, 0x27, 0x4c, 0x09, 0x69, 0x9c, 0x71, 0x0e, 0xfb, 0x4f, 0x1e, 0x42, 0x99, 0x36,
0x84, 0x2f, 0x41, 0xc1, 0xf7, 0x9a, 0xf9, 0x6b, 0xf9, 0x1b, 0x75, 0xa7, 0xe0, 0x7b, 0xfc, 0x16,
0x54, 0xf6, 0x7d, 0x11, 0x78, 0x6f, 0xdc, 0x17, 0x43, 0xc6, 0x1f, 0xc1, 0x42, 0x24, 0x62, 0x15,
0xf9, 0x66, 0xfe, 0x7a, 0x6b, 0xbe, 0x3a, 0x6b, 0xf7, 0x57, 0x9d, 0x0c, 0xa1, 0x33, 0xc6, 0x86,
0xeb, 0xdc, 0xe9, 0xf9, 0x81, 0x17, 0x89, 0x70, 0xdb, 0xd3, 0xbb, 0x54, 0x77, 0xb2, 0x28, 0x7e,
0x03, 0xce, 0xb5, 0xdd, 0xce, 0x41, 0x37, 0x92, 0xc3, 0x10, 0x97, 0x44, 0x46, 0xcd, 0x32, 0x0d,
0x7b, 0x12, 0xcd, 0xdf, 0x81, 0xb2, 0x1b, 0xf8, 0xdd, 0x90, 0xf6, 0x62, 0xe9, 0x8e, 0x35, 0x73,
0x2c, 0x6b, 0x48, 0xe1, 0x68, 0x42, 0xbe, 0x05, 0x8b, 0x87, 0x22, 0x52, 0x7e, 0xc7, 0x0d, 0x08,
0xdf, 0xac, 0x12, 0xa7, 0x3d, 0x93, 0xf3, 0x65, 0x96, 0xd2, 0x19, 0x67, 0xe4, 0xdb, 0x00, 0x31,
0x1e, 0x10, 0xd2, 0xf3, 0x66, 0x83, 0x16, 0xe3, 0xeb, 0x33, 0xc5, 0x6c, 0xc8, 0x50, 0x89, 0x50,
0xad, 0xb6, 0x52, 0xf2, 0xad, 0x9c, 0x93, 0x61, 0xe6, 0xef, 0x42, 0x49, 0x89, 0x23, 0xd5, 0x5c,
0x3a, 0x65, 0x45, 0x13, 0x21, 0x7b, 0xe2, 0x48, 0x6d, 0xe5, 0x1c, 0x62, 0x40, 0x46, 0x3c, 0x00,
0xcd, 0x73, 0x73, 0x30, 0x3e, 0xf6, 0x03, 0x81, 0x8c, 0xc8, 0xc0, 0xdf, 0x87, 0x4a, 0xe0, 0x1e,
0xcb, 0xa1, 0x6a, 0x32, 0x62, 0xfd, 0x85, 0x53, 0x59, 0x9f, 0x12, 0xe9, 0x56, 0xce, 0x31, 0x4c,
0xfc, 0x1e, 0x14, 0x3d, 0xff, 0xb0, 0xb9, 0x4c, 0xbc, 0xd7, 0x4e, 0xe5, 0xdd, 0xf4, 0x0f, 0xb7,
0x72, 0x0e, 0x92, 0xf3, 0x0d, 0xa8, 0xb5, 0xa5, 0x3c, 0xe8, 0xbb, 0xd1, 0x41, 0x93, 0x13, 0xeb,
0xd7, 0x4e, 0x65, 0x5d, 0x37, 0xc4, 0x5b, 0x39, 0x27, 0x65, 0xc4, 0x29, 0xfb, 0x1d, 0x19, 0x36,
0xcf, 0xcf, 0x31, 0xe5, 0xed, 0x8e, 0x0c, 0x71, 0xca, 0xc8, 0x80, 0x8c, 0x81, 0x1f, 0x1e, 0x34,
0x57, 0xe6, 0x60, 0xc4, 0xb3, 0x83, 0x8c, 0xc8, 0x80, 0xc3, 0xf6, 0x5c, 0xe5, 0x1e, 0xfa, 0xe2,
0x75, 0xf3, 0xc2, 0x1c, 0xc3, 0xde, 0x34, 0xc4, 0x38, 0xec, 0x84, 0x11, 0x85, 0x24, 0x07, 0xb3,
0x79, 0x71, 0x0e, 0x21, 0xc9, 0x99, 0x46, 0x21, 0x09, 0x23, 0xff, 0x35, 0x58, 0xde, 0x17, 0xae,
0x1a, 0x46, 0xc2, 0x1b, 0x99, 0xb9, 0x4b, 0x24, 0x6d, 0xf5, 0xf4, 0xbd, 0x9f, 0xe4, 0xda, 0xca,
0x39, 0xd3, 0xa2, 0xf8, 0x77, 0xa1, 0x1c, 0xb8, 0x4a, 0x1c, 0x35, 0x9b, 0x24, 0xd3, 0x7e, 0x83,
0x52, 0x28, 0x71, 0xb4, 0x95, 0x73, 0x34, 0x0b, 0xff, 0x65, 0x38, 0xa7, 0xdc, 0x76, 0x20, 0x76,
0xf6, 0x0d, 0x41, 0xdc, 0xfc, 0x39, 0x92, 0xf2, 0xf6, 0xe9, 0xea, 0x3c, 0xce, 0xb3, 0x95, 0x73,
0x26, 0xc5, 0xe0, 0xa8, 0x08, 0xd5, 0xb4, 0xe6, 0x18, 0x15, 0xc9, 0xc3, 0x51, 0x11, 0x0b, 0x7f,
0x0a, 0x0d, 0xfa, 0xd8, 0x90, 0xc1, 0xb0, 0x1f, 0x36, 0x2f, 0x93, 0x84, 0x1b, 0x6f, 0x96, 0xa0,
0xe9, 0xb7, 0x72, 0x4e, 0x96, 0x1d, 0x37, 0x91, 0x40, 0x47, 0xbe, 0x6e, 0x5e, 0x99, 0x63, 0x13,
0xf7, 0x0c, 0x31, 0x6e, 0x62, 0xc2, 0x88, 0x47, 0xef, 0xb5, 0xef, 0x75, 0x85, 0x6a, 0x7e, 0x65,
0x8e, 0xa3, 0xf7, 0x8a, 0x48, 0xf1, 0xe8, 0x69, 0x26, 0xeb, 0x87, 0xb0, 0x90, 0x35, 0xae, 0x9c,
0x43, 0x29, 0x12, 0xae, 0x36, 0xec, 0x35, 0x87, 0xbe, 0x11, 0x27, 0x3c, 0x5f, 0x91, 0x61, 0xaf,
0x39, 0xf4, 0xcd, 0x2f, 0x42, 0x45, 0x3b, 0x19, 0xb2, 0xdb, 0x35, 0xc7, 0x40, 0x48, 0xeb, 0x45,
0x6e, 0xb7, 0x59, 0xd2, 0xb4, 0xf8, 0x8d, 0xb4, 0x5e, 0x24, 0x07, 0x3b, 0x21, 0xd9, 0xdd, 0x9a,
0x63, 0x20, 0xeb, 0x9f, 0x6f, 0x43, 0xd5, 0x0c, 0xcc, 0xfa, 0xa3, 0x3c, 0x54, 0xb4, 0x5d, 0xe0,
0x0f, 0xa0, 0x1c, 0xab, 0xe3, 0x40, 0xd0, 0x18, 0x96, 0xee, 0x7c, 0x63, 0x0e, 0x5b, 0xb2, 0xda,
0x42, 0x06, 0x47, 0xf3, 0xd9, 0x0e, 0x94, 0x09, 0xe6, 0x55, 0x28, 0x3a, 0xf2, 0x35, 0xcb, 0x71,
0x80, 0x8a, 0x5e, 0x73, 0x96, 0x47, 0xe4, 0xa6, 0x7f, 0xc8, 0x0a, 0x88, 0xdc, 0x12, 0xae, 0x27,
0x22, 0x56, 0xe4, 0x8b, 0x50, 0x4f, 0x56, 0x37, 0x66, 0x25, 0xce, 0x60, 0x21, 0xb3, 0x6f, 0x31,
0x2b, 0x5b, 0xff, 0x5d, 0x82, 0x12, 0x1e, 0x63, 0xfe, 0x16, 0x2c, 0x2a, 0x37, 0xea, 0x0a, 0x1d,
0xc9, 0x6c, 0x27, 0x2e, 0x70, 0x1c, 0xc9, 0xdf, 0x4f, 0xe6, 0x50, 0xa0, 0x39, 0x7c, 0xfd, 0x8d,
0xe6, 0x61, 0x6c, 0x06, 0x19, 0x67, 0x5a, 0x9c, 0xcf, 0x99, 0x3e, 0x86, 0x1a, 0x5a, 0xa5, 0x96,
0xff, 0x43, 0x41, 0x4b, 0xbf, 0x74, 0xe7, 0xe6, 0x9b, 0xbb, 0xdc, 0x36, 0x1c, 0x4e, 0xca, 0xcb,
0xb7, 0xa1, 0xde, 0x71, 0x23, 0x8f, 0x06, 0x43, 0xbb, 0xb5, 0x74, 0xe7, 0x9b, 0x6f, 0x16, 0xb4,
0x91, 0xb0, 0x38, 0x23, 0x6e, 0xbe, 0x03, 0x0d, 0x4f, 0xc4, 0x9d, 0xc8, 0x1f, 0x90, 0x95, 0xd2,
0x2e, 0xf5, 0x5b, 0x6f, 0x16, 0xb6, 0x39, 0x62, 0x72, 0xb2, 0x12, 0xf8, 0x15, 0xa8, 0x47, 0xa9,
0x99, 0xaa, 0x92, 0x9f, 0x1f, 0x21, 0xec, 0x77, 0xa1, 0x96, 0xcc, 0x87, 0x2f, 0x40, 0x0d, 0x7f,
0x9f, 0xcb, 0x50, 0xb0, 0x1c, 0xee, 0x2d, 0x42, 0xad, 0xbe, 0x1b, 0x04, 0x2c, 0xcf, 0x97, 0x00,
0x10, 0x7c, 0x26, 0x3c, 0x7f, 0xd8, 0x67, 0x05, 0xfb, 0x17, 0x13, 0x6d, 0xa9, 0x41, 0x69, 0xd7,
0xed, 0x22, 0xc7, 0x02, 0xd4, 0x12, 0xab, 0xcb, 0xf2, 0xc8, 0xbf, 0xe9, 0xc6, 0xbd, 0xb6, 0x74,
0x23, 0x8f, 0x15, 0x78, 0x03, 0xaa, 0x6b, 0x51, 0xa7, 0xe7, 0x1f, 0x0a, 0x56, 0xb4, 0x6f, 0x41,
0x23, 0x33, 0x5e, 0x14, 0x61, 0x3a, 0xad, 0x43, 0x79, 0xcd, 0xf3, 0x84, 0xc7, 0xf2, 0xc8, 0x60,
0x26, 0xc8, 0x0a, 0xf6, 0x37, 0xa1, 0x9e, 0xae, 0x16, 0x92, 0xa3, 0xff, 0x65, 0x39, 0xfc, 0x42,
0x34, 0xcb, 0xa3, 0x56, 0x6e, 0x87, 0x81, 0x1f, 0x0a, 0x56, 0xb0, 0x7e, 0x40, 0xaa, 0xca, 0x7f,
0x69, 0xfc, 0x40, 0x5c, 0x7f, 0x93, 0x83, 0x1c, 0x3f, 0x0d, 0x97, 0x33, 0xf3, 0x7b, 0xea, 0xd3,
0xe0, 0x6a, 0x50, 0xda, 0x94, 0x2a, 0x66, 0x79, 0xeb, 0xbf, 0x0a, 0x50, 0x4b, 0xfc, 0x22, 0x67,
0x50, 0x1c, 0x46, 0x81, 0x51, 0x68, 0xfc, 0xe4, 0x2b, 0x50, 0x56, 0xbe, 0x32, 0x6a, 0x5c, 0x77,
0x34, 0x80, 0x21, 0x57, 0x76, 0x67, 0x8b, 0xd4, 0x36, 0xb9, 0x55, 0x7e, 0xdf, 0xed, 0x8a, 0x2d,
0x37, 0xee, 0x91, 0x3e, 0xd6, 0x9d, 0x11, 0x02, 0xf9, 0xf7, 0xdd, 0x43, 0xd4, 0x39, 0x6a, 0xd7,
0xc1, 0x58, 0x16, 0xc5, 0xef, 0x42, 0x09, 0x27, 0x68, 0x94, 0xe6, 0xe7, 0x27, 0x26, 0x8c, 0x6a,
0xb2, 0x1b, 0x09, 0xdc, 0x9e, 0x55, 0x0c, 0xa5, 0x1d, 0x22, 0xe6, 0xd7, 0x61, 0x49, 0x1f, 0xc2,
0x1d, 0x0a, 0xb2, 0xb7, 0x3d, 0x0a, 0xc6, 0xea, 0xce, 0x04, 0x96, 0xaf, 0xe1, 0x72, 0xba, 0x4a,
0x34, 0x6b, 0x73, 0xe8, 0x77, 0xb2, 0x38, 0xab, 0x2d, 0x64, 0x71, 0x34, 0xa7, 0x7d, 0x1f, 0xd7,
0xd4, 0x55, 0x02, 0xb7, 0xf9, 0x51, 0x7f, 0xa0, 0x8e, 0xb5, 0xd2, 0x3c, 0x16, 0xaa, 0xd3, 0xf3,
0xc3, 0x2e, 0xcb, 0xeb, 0x25, 0xc6, 0x4d, 0x24, 0x92, 0x28, 0x92, 0x11, 0x2b, 0x5a, 0x16, 0x94,
0x50, 0x47, 0xd1, 0x48, 0x86, 0x6e, 0x5f, 0x98, 0x95, 0xa6, 0x6f, 0xeb, 0x3c, 0x2c, 0x4f, 0xb9,
0x55, 0xeb, 0xaf, 0x2a, 0x5a, 0x43, 0x90, 0x83, 0x42, 0x3a, 0xc3, 0x41, 0xd1, 0xda, 0x99, 0x6c,
0x0c, 0x4a, 0x19, 0xb7, 0x31, 0xef, 0x43, 0x19, 0x27, 0x96, 0x98, 0x98, 0x39, 0xd8, 0x9f, 0x21,
0xb9, 0xa3, 0xb9, 0x78, 0x13, 0xaa, 0x9d, 0x9e, 0xe8, 0x1c, 0x08, 0xcf, 0xd8, 0xfa, 0x04, 0x44,
0xa5, 0xe9, 0x64, 0xa2, 0x6c, 0x0d, 0x90, 0x4a, 0x74, 0x64, 0xf8, 0xa8, 0x2f, 0x3f, 0xf6, 0x69,
0x5f, 0x51, 0x25, 0x12, 0x44, 0xd2, 0xba, 0x8d, 0x3a, 0x62, 0xb6, 0x6d, 0x84, 0xb0, 0x1e, 0x41,
0x99, 0xfa, 0xc6, 0x93, 0xa0, 0xc7, 0xac, 0x53, 0xc5, 0xeb, 0xf3, 0x8d, 0xd9, 0x0c, 0xd9, 0xfa,
0xd3, 0x02, 0x94, 0x10, 0xe6, 0x37, 0xa1, 0x1c, 0xb9, 0x61, 0x57, 0x6f, 0xc0, 0x74, 0xc6, 0xe9,
0x60, 0x9b, 0xa3, 0x49, 0xf8, 0x03, 0xa3, 0x8a, 0x85, 0x39, 0x94, 0x25, 0xed, 0x31, 0xab, 0x96,
0x2b, 0x50, 0x1e, 0xb8, 0x91, 0xdb, 0x37, 0xe7, 0x44, 0x03, 0xf6, 0x4f, 0xf3, 0x50, 0x42, 0x22,
0xbe, 0x0c, 0x8b, 0x2d, 0x15, 0xf9, 0x07, 0x42, 0xf5, 0x22, 0x39, 0xec, 0xf6, 0xb4, 0x26, 0x3d,
0x11, 0xc7, 0xda, 0xde, 0x68, 0x83, 0xa0, 0xdc, 0xc0, 0xef, 0xb0, 0x02, 0x6a, 0xd5, 0xba, 0x0c,
0x3c, 0x56, 0xe4, 0xe7, 0xa0, 0xf1, 0x22, 0xf4, 0x44, 0x14, 0x77, 0x64, 0x24, 0x3c, 0x56, 0x32,
0xa7, 0xfb, 0x80, 0x95, 0xc9, 0x97, 0x89, 0x23, 0x45, 0x29, 0x0d, 0xab, 0xf0, 0xf3, 0x70, 0x6e,
0x7d, 0x3c, 0xcf, 0x61, 0x55, 0xb4, 0x49, 0xcf, 0x44, 0x88, 0x4a, 0xc6, 0x6a, 0x5a, 0x89, 0xe5,
0xc7, 0x3e, 0xab, 0x63, 0x67, 0xfa, 0x9c, 0x30, 0xb0, 0xff, 0x26, 0x9f, 0x58, 0x8e, 0x45, 0xa8,
0xef, 0xba, 0x91, 0xdb, 0x8d, 0xdc, 0x01, 0x8e, 0xaf, 0x01, 0x55, 0xed, 0x38, 0x6f, 0x6b, 0xeb,
0xa6, 0x81, 0x3b, 0xda, 0x36, 0x6a, 0xe0, 0x2e, 0x2b, 0x8e, 0x80, 0x7b, 0xac, 0x84, 0x7d, 0x7c,
0x38, 0x94, 0x4a, 0xb0, 0x32, 0xd9, 0x3a, 0xe9, 0x09, 0x56, 0x41, 0xe4, 0x1e, 0x5a, 0x14, 0x56,
0xc5, 0x39, 0x6f, 0xa0, 0xfe, 0xb4, 0xe5, 0x11, 0xab, 0xe1, 0x30, 0x70, 0x19, 0x85, 0xc7, 0xea,
0xd8, 0xf2, 0x7c, 0xd8, 0x6f, 0x0b, 0x9c, 0x26, 0x60, 0xcb, 0x9e, 0xec, 0x76, 0x03, 0xc1, 0x1a,
0xb8, 0x06, 0x19, 0xe3, 0xcb, 0x16, 0xc8, 0xd2, 0xba, 0x41, 0x20, 0x87, 0x8a, 0x2d, 0x5a, 0x9f,
0x15, 0xa1, 0x84, 0x49, 0x0a, 0x9e, 0x9d, 0x1e, 0xda, 0x19, 0x73, 0x76, 0xf0, 0x3b, 0x3d, 0x81,
0x85, 0xd1, 0x09, 0xe4, 0xdf, 0x35, 0x3b, 0x5d, 0x9c, 0xc3, 0xca, 0xa2, 0xe0, 0xec, 0x26, 0x73,
0x28, 0xf5, 0xfd, 0xbe, 0x30, 0xb6, 0x8e, 0xbe, 0x11, 0x17, 0xa3, 0x3f, 0xc6, 0x63, 0x50, 0x74,
0xe8, 0x1b, 0x4f, 0x8d, 0x8b, 0x6e, 0x61, 0x4d, 0xd1, 0x19, 0x28, 0x3a, 0x09, 0xa8, 0x4f, 0x33,
0x5a, 0xa5, 0xea, 0x1c, 0xa7, 0x99, 0xba, 0xcf, 0x5a, 0xa4, 0x91, 0x31, 0xa8, 0xcd, 0xcf, 0x9e,
0x71, 0x12, 0x9b, 0x46, 0x1b, 0x47, 0x0e, 0xac, 0xa6, 0x57, 0x8f, 0xe5, 0x71, 0x97, 0xe8, 0x18,
0x6a, 0x5b, 0xf6, 0xd2, 0xf7, 0x84, 0x64, 0x45, 0x72, 0x70, 0x43, 0xcf, 0x97, 0xac, 0x84, 0x11,
0xd5, 0xee, 0xe6, 0x63, 0x56, 0xb6, 0xaf, 0x67, 0x5c, 0xcd, 0xda, 0x50, 0x49, 0x2d, 0x86, 0xd4,
0x32, 0xaf, 0xb5, 0xac, 0x2d, 0x3c, 0x56, 0xb0, 0xbf, 0x3d, 0xc3, 0x7c, 0x2e, 0x42, 0xfd, 0xc5,
0x20, 0x90, 0xae, 0x77, 0x8a, 0xfd, 0x5c, 0x00, 0x18, 0x25, 0xbd, 0xd6, 0x1f, 0x5e, 0x1e, 0xb9,
0x69, 0x8c, 0x31, 0x63, 0x39, 0x8c, 0x3a, 0x82, 0x4c, 0x43, 0xdd, 0x31, 0x10, 0x7f, 0x08, 0x65,
0x6c, 0x8f, 0x9b, 0x05, 0xb2, 0x18, 0x37, 0xe7, 0x4a, 0xb5, 0x56, 0x5f, 0xfa, 0xe2, 0xb5, 0xa3,
0x19, 0xf9, 0xfd, 0x6c, 0xd8, 0xf1, 0x86, 0x22, 0xd0, 0x88, 0x92, 0x5f, 0x05, 0x70, 0x3b, 0xca,
0x3f, 0x14, 0x28, 0xcb, 0x9c, 0xfd, 0x0c, 0x86, 0x3b, 0xd0, 0xc0, 0x23, 0x39, 0xd8, 0x89, 0xf0,
0x14, 0x37, 0x17, 0x48, 0xf0, 0x3b, 0xf3, 0x0d, 0xef, 0x7b, 0x29, 0xa3, 0x93, 0x15, 0xc2, 0x5f,
0xc0, 0x82, 0x2e, 0x30, 0x19, 0xa1, 0x8b, 0x24, 0xf4, 0xf6, 0x7c, 0x42, 0x77, 0x46, 0x9c, 0xce,
0x98, 0x98, 0xe9, 0xba, 0x51, 0xf9, 0xac, 0x75, 0x23, 0xeb, 0xaf, 0xcb, 0x50, 0xa2, 0x69, 0x4f,
0x96, 0x8d, 0x36, 0xc6, 0xcc, 0xeb, 0xad, 0xf9, 0xb7, 0x67, 0xe2, 0xf4, 0xd1, 0x69, 0x2e, 0x66,
0x4e, 0xf3, 0x43, 0x28, 0xc7, 0x32, 0x52, 0xc9, 0x96, 0xcd, 0xb9, 0xf1, 0x2d, 0x19, 0x29, 0x47,
0x33, 0xf2, 0xc7, 0x50, 0xdd, 0xf7, 0x03, 0x85, 0x0b, 0xa9, 0x27, 0xfc, 0xf6, 0x7c, 0x32, 0x1e,
0x13, 0x93, 0x93, 0x30, 0xf3, 0xa7, 0x59, 0x05, 0xaa, 0x90, 0xa4, 0xd5, 0xf9, 0x24, 0xcd, 0xd2,
0xab, 0x9b, 0xc0, 0x3a, 0xf2, 0x50, 0x44, 0x49, 0xdb, 0x13, 0x71, 0x6c, 0x1c, 0xe6, 0x14, 0x9e,
0x5b, 0x50, 0xeb, 0xf9, 0x9e, 0xc0, 0x98, 0x83, 0xec, 0x42, 0xcd, 0x49, 0x61, 0xfe, 0x04, 0x6a,
0x14, 0xab, 0xa3, 0x85, 0xaa, 0x9f, 0x79, 0xf1, 0x75, 0xda, 0x90, 0x08, 0xc0, 0x8e, 0xa8, 0xf3,
0xc7, 0xbe, 0x6a, 0x82, 0xee, 0x28, 0x81, 0x71, 0xc0, 0xa4, 0xa3, 0xd9, 0x01, 0x37, 0xf4, 0x80,
0x27, 0xf1, 0xfc, 0x1e, 0x5c, 0x20, 0xdc, 0x84, 0xc3, 0xc2, 0xe3, 0x81, 0x42, 0x67, 0x37, 0xda,
0xf7, 0x8c, 0xf1, 0x42, 0x77, 0x82, 0x59, 0x5b, 0x62, 0x76, 0x62, 0xa5, 0xfd, 0xd3, 0xf7, 0xdc,
0x20, 0x10, 0xd1, 0xb1, 0x4e, 0xf9, 0x9e, 0xb8, 0x61, 0xdb, 0x0d, 0x59, 0xd1, 0xbe, 0x01, 0x25,
0x1a, 0x7b, 0x1d, 0xca, 0x3a, 0x35, 0xa0, 0x34, 0xd1, 0xa4, 0x05, 0x64, 0xae, 0x9e, 0x62, 0xdc,
0xc8, 0x0a, 0xd6, 0x5f, 0x16, 0xa1, 0x96, 0x8c, 0x12, 0x83, 0xe4, 0x03, 0x71, 0x9c, 0x04, 0xc9,
0x07, 0xe2, 0x98, 0x62, 0x97, 0xf8, 0xa5, 0x1f, 0xfb, 0x6d, 0x13, 0x8b, 0xd5, 0x9c, 0x11, 0x02,
0xdd, 0xff, 0x6b, 0xdf, 0x53, 0x3d, 0x52, 0xce, 0xb2, 0xa3, 0x01, 0x7e, 0x03, 0xce, 0x79, 0xae,
0x12, 0xdb, 0x61, 0x27, 0x18, 0x7a, 0x62, 0x0f, 0x5d, 0x87, 0xce, 0x8d, 0x27, 0xd1, 0xfc, 0xfb,
0x00, 0xca, 0xef, 0x8b, 0xc7, 0x32, 0xea, 0xbb, 0xca, 0x04, 0xc4, 0xdf, 0x39, 0x9b, 0xfa, 0xac,
0xee, 0xa5, 0x02, 0x9c, 0x8c, 0x30, 0x14, 0x8d, 0xbd, 0x19, 0xd1, 0xd5, 0x2f, 0x25, 0x7a, 0x33,
0x15, 0xe0, 0x64, 0x84, 0xd9, 0xbf, 0x02, 0x30, 0x6a, 0xe1, 0x17, 0x81, 0x3f, 0x93, 0xa1, 0xea,
0xad, 0xb5, 0xdb, 0xd1, 0xba, 0xd8, 0x97, 0x91, 0xd8, 0x74, 0xd1, 0xe6, 0x5f, 0x80, 0xe5, 0x14,
0xbf, 0xb6, 0xaf, 0x44, 0x84, 0x68, 0x5a, 0xfa, 0x56, 0x4f, 0x46, 0x4a, 0x07, 0x14, 0xf4, 0xf9,
0xa2, 0xc5, 0x8a, 0xe8, 0x67, 0xb6, 0x5b, 0x3b, 0xac, 0x64, 0xdf, 0x00, 0x18, 0x4d, 0x89, 0x02,
0x6f, 0xfa, 0xba, 0x7d, 0xc7, 0x84, 0xe1, 0x04, 0xdd, 0xb9, 0xc7, 0xf2, 0xd6, 0x3f, 0xe6, 0xa1,
0x84, 0x67, 0x1a, 0x73, 0x8e, 0xac, 0x02, 0xea, 0xed, 0xcb, 0xa2, 0xbe, 0x9c, 0x25, 0x42, 0xd9,
0x59, 0x4b, 0xf4, 0x1e, 0x34, 0x3a, 0xc3, 0x58, 0xc9, 0x3e, 0x99, 0xce, 0x66, 0x91, 0x4e, 0xfb,
0xc5, 0xa9, 0xec, 0xfd, 0xa5, 0x1b, 0x0c, 0x85, 0x93, 0x25, 0xb5, 0xbf, 0x66, 0x94, 0xb8, 0x0a,
0xc5, 0xb5, 0xb8, 0x63, 0x92, 0x34, 0x11, 0x77, 0x74, 0x04, 0xb8, 0x41, 0x94, 0xac, 0x60, 0xfd,
0x59, 0x15, 0x2a, 0xda, 0xc0, 0xf0, 0x0f, 0xa1, 0x26, 0x07, 0x22, 0x72, 0x95, 0x8c, 0x4c, 0x66,
0x78, 0xff, 0x2c, 0x06, 0x6a, 0x75, 0xc7, 0x30, 0x3b, 0xa9, 0x98, 0xc9, 0x55, 0x2a, 0x4c, 0xaf,
0xd2, 0x4d, 0x60, 0x89, 0x2d, 0xda, 0x8d, 0x90, 0x4f, 0x1d, 0x9b, 0x38, 0x7f, 0x0a, 0xcf, 0xf7,
0xa0, 0xde, 0x91, 0xa1, 0xe7, 0xa7, 0x59, 0xe2, 0xd2, 0x9d, 0x6f, 0x9f, 0x69, 0x84, 0x1b, 0x09,
0xb7, 0x33, 0x12, 0xc4, 0xdf, 0x86, 0xf2, 0x21, 0x2e, 0x1f, 0xc5, 0x5a, 0x27, 0x2f, 0xae, 0x26,
0xe2, 0x1f, 0x41, 0xe3, 0x93, 0xa1, 0xdf, 0x39, 0xd8, 0xc9, 0x56, 0x21, 0xde, 0x3b, 0xd3, 0x28,
0x3e, 0x1c, 0xf1, 0x3b, 0x59, 0x61, 0xfc, 0x3e, 0x54, 0xf6, 0xb3, 0x67, 0xe7, 0x2b, 0x27, 0x38,
0x44, 0x73, 0x3e, 0x0c, 0x31, 0x2e, 0xb2, 0x9f, 0x39, 0xf7, 0xda, 0x30, 0x67, 0x51, 0xf6, 0x65,
0xa8, 0x25, 0x9b, 0x43, 0xfa, 0x10, 0x7a, 0x2c, 0xc7, 0x2b, 0x50, 0xd8, 0x89, 0x58, 0xde, 0xfe,
0x22, 0x0f, 0xf5, 0x74, 0x61, 0xc6, 0x2b, 0x0e, 0x8f, 0x3e, 0x19, 0xba, 0x01, 0xcb, 0x53, 0xc8,
0x2c, 0x95, 0x86, 0xe8, 0x0c, 0x7d, 0x2f, 0x12, 0xae, 0xa2, 0x42, 0x17, 0x1a, 0x46, 0x11, 0xc7,
0xac, 0xc4, 0x39, 0x2c, 0x19, 0xf4, 0x4e, 0xa4, 0x49, 0xcb, 0x18, 0x51, 0x63, 0x6b, 0x82, 0xa8,
0x68, 0x3b, 0x7a, 0x20, 0x74, 0xc6, 0xf0, 0x5c, 0x2a, 0x02, 0x6a, 0x38, 0x96, 0xed, 0x90, 0xd5,
0xb1, 0xcf, 0xe7, 0x52, 0x6d, 0x87, 0x0c, 0x46, 0xa1, 0x5c, 0x23, 0xe9, 0x9e, 0xa0, 0x05, 0x0a,
0x14, 0x83, 0x60, 0x3b, 0x64, 0x8b, 0xa6, 0x41, 0x43, 0x4b, 0x28, 0xf1, 0xd1, 0x91, 0xdb, 0x41,
0xf6, 0x73, 0x7c, 0x09, 0x00, 0x79, 0x0c, 0xcc, 0xec, 0x7f, 0xc8, 0x43, 0x23, 0xb3, 0xf0, 0x18,
0x1e, 0x52, 0x23, 0x5a, 0x15, 0x1d, 0x2d, 0x7e, 0x5f, 0xc4, 0x4a, 0x44, 0x5e, 0x62, 0x31, 0xf6,
0x24, 0x7e, 0x16, 0xb0, 0x8f, 0x3d, 0xd9, 0x97, 0x51, 0x24, 0x5f, 0xb3, 0x22, 0x42, 0x4f, 0xdd,
0x58, 0xbd, 0x12, 0xe2, 0x80, 0x95, 0x70, 0x7a, 0x1b, 0xc3, 0x28, 0x12, 0xa1, 0x46, 0x94, 0x69,
0x40, 0xe2, 0x48, 0x43, 0x15, 0x14, 0x8a, 0xc4, 0x64, 0x92, 0x58, 0x95, 0x33, 0x58, 0x30, 0xd4,
0x1a, 0x53, 0x43, 0x02, 0x24, 0xd7, 0x60, 0x1d, 0x33, 0x2b, 0x9d, 0x99, 0xec, 0xec, 0x6f, 0xba,
0xc7, 0xf1, 0x5a, 0x57, 0x32, 0x98, 0x44, 0x3e, 0x97, 0xaf, 0x59, 0xc3, 0x1a, 0x02, 0x8c, 0x62,
0x36, 0x8c, 0x55, 0x51, 0xbf, 0xd2, 0xda, 0xa1, 0x81, 0xf8, 0x0e, 0x00, 0x7e, 0x11, 0x65, 0x12,
0xb0, 0x9e, 0xc1, 0x29, 0x13, 0x9f, 0x93, 0x11, 0x61, 0xfd, 0x3a, 0xd4, 0xd3, 0x06, 0x4c, 0x3d,
0xc8, 0x7d, 0xa6, 0xdd, 0x26, 0x20, 0xba, 0x28, 0x3f, 0xf4, 0xc4, 0x11, 0x9d, 0xf7, 0xb2, 0xa3,
0x01, 0x1c, 0x65, 0xcf, 0xf7, 0x3c, 0x11, 0x26, 0x15, 0x5e, 0x0d, 0xcd, 0xba, 0x4e, 0x2b, 0xcd,
0xbc, 0x4e, 0xb3, 0x7e, 0x15, 0x1a, 0x99, 0xa0, 0xf2, 0xc4, 0x69, 0x67, 0x06, 0x56, 0x18, 0x1f,
0xd8, 0x15, 0xa8, 0x4b, 0x53, 0xb5, 0x89, 0xc9, 0x96, 0xd6, 0x9d, 0x11, 0xc2, 0xfa, 0x8b, 0x02,
0x94, 0xf5, 0xd4, 0x26, 0x83, 0xca, 0xc7, 0x50, 0xc1, 0xac, 0x68, 0x98, 0xdc, 0x45, 0xce, 0x19,
0xb8, 0xb5, 0x88, 0x67, 0x2b, 0xe7, 0x18, 0x6e, 0xfe, 0x3e, 0x14, 0x95, 0xdb, 0x35, 0x05, 0x92,
0x6f, 0xcc, 0x27, 0x64, 0xcf, 0xed, 0x6e, 0xe5, 0x1c, 0xe4, 0xe3, 0x4f, 0xa1, 0xd6, 0x31, 0x39,
0xad, 0x31, 0x56, 0x73, 0xc6, 0x7d, 0x49, 0x26, 0xbc, 0x95, 0x73, 0x52, 0x09, 0xfc, 0x21, 0x94,
0xd0, 0xc1, 0x92, 0xb5, 0x9d, 0x3b, 0x9e, 0xc5, 0xe3, 0xb2, 0x95, 0x73, 0x88, 0x73, 0xbd, 0x0a,
0x65, 0xb2, 0x8d, 0x56, 0x13, 0x2a, 0x7a, 0xae, 0x93, 0x2b, 0x67, 0x5d, 0x82, 0xe2, 0x9e, 0xdb,
0xc5, 0x20, 0xc7, 0xf7, 0x62, 0x93, 0x4a, 0xe1, 0xa7, 0xf5, 0xd6, 0x28, 0x3f, 0xcf, 0x96, 0x7e,
0xf2, 0x63, 0xa5, 0x1f, 0xab, 0x02, 0x25, 0xec, 0xd1, 0xba, 0x72, 0x5a, 0xc0, 0x64, 0x5d, 0xc6,
0xd0, 0x4a, 0x89, 0xa3, 0x59, 0x55, 0x2d, 0x6b, 0x19, 0xce, 0x4d, 0x5c, 0xe2, 0x58, 0x55, 0x13,
0xd7, 0x59, 0x8b, 0xd0, 0xc8, 0x94, 0xe5, 0xad, 0xeb, 0x50, 0x4b, 0x8a, 0xf6, 0x18, 0x81, 0xfa,
0xb1, 0x2e, 0x37, 0x98, 0x41, 0xa5, 0xb0, 0xf5, 0x31, 0x54, 0xf4, 0xbd, 0x07, 0x5f, 0x4f, 0xef,
0x29, 0xf3, 0x73, 0x14, 0xc9, 0x35, 0x93, 0xb9, 0x62, 0x48, 0x2e, 0x2b, 0xed, 0x2b, 0xe9, 0x45,
0x45, 0x92, 0xdb, 0x92, 0xaf, 0xde, 0x8b, 0x84, 0x60, 0x79, 0x7b, 0x1f, 0x6a, 0xbb, 0x32, 0x9e,
0xb4, 0xcd, 0x55, 0x28, 0xee, 0xc9, 0x81, 0x76, 0xe5, 0xeb, 0x52, 0x91, 0x2b, 0xd7, 0xa6, 0x78,
0x5f, 0xe9, 0x5c, 0xda, 0xf1, 0xbb, 0x3d, 0xa5, 0xeb, 0x24, 0xdb, 0x61, 0x28, 0x22, 0x56, 0x46,
0xfb, 0xe8, 0x88, 0x41, 0xe0, 0x76, 0x04, 0xab, 0xa0, 0x7d, 0x24, 0xfc, 0x63, 0x3f, 0x8a, 0x15,
0xab, 0xda, 0xef, 0xa2, 0x55, 0xf5, 0xbb, 0x64, 0x18, 0xe9, 0x83, 0x44, 0xe5, 0xd0, 0xc4, 0x11,
0xb8, 0x21, 0x42, 0x34, 0xf8, 0x54, 0xee, 0xd6, 0xf7, 0xcd, 0xd4, 0x41, 0xc1, 0x7e, 0x05, 0x8b,
0x63, 0xf7, 0xd0, 0x7c, 0x05, 0xd8, 0x18, 0x02, 0x07, 0x9a, 0xe3, 0x97, 0xe0, 0xfc, 0x18, 0xf6,
0x99, 0xef, 0x79, 0x54, 0x0d, 0x98, 0x6c, 0x48, 0xa6, 0xb3, 0x5e, 0x87, 0x6a, 0x47, 0x2f, 0x9c,
0xbd, 0x0b, 0x8b, 0xb4, 0x92, 0xcf, 0x84, 0x72, 0x77, 0xc2, 0xe0, 0xf8, 0xff, 0xfd, 0x58, 0xc0,
0xfe, 0x26, 0x94, 0xa9, 0x2a, 0x87, 0x2a, 0xb3, 0x1f, 0xc9, 0x3e, 0xc9, 0x2a, 0x3b, 0xf4, 0x8d,
0xd2, 0x95, 0x34, 0xc6, 0xab, 0xa0, 0xa4, 0xfd, 0x4f, 0x00, 0xd5, 0xb5, 0x4e, 0x47, 0x0e, 0x43,
0x35, 0xd5, 0xf3, 0xac, 0xc2, 0xcf, 0x7d, 0xa8, 0xb8, 0x87, 0xae, 0x72, 0x23, 0x73, 0xd2, 0x27,
0xfd, 0xb8, 0x91, 0xb5, 0xba, 0x46, 0x44, 0x8e, 0x21, 0x46, 0xb6, 0x8e, 0x0c, 0xf7, 0xfd, 0xae,
0x39, 0xdc, 0x27, 0xb1, 0x6d, 0x10, 0x91, 0x63, 0x88, 0x91, 0xcd, 0x18, 0xa7, 0xf2, 0xa9, 0x6c,
0xfa, 0x84, 0xa6, 0xb6, 0xe8, 0x16, 0x94, 0xfc, 0x70, 0x5f, 0x9a, 0x67, 0x22, 0x97, 0x4f, 0x60,
0xda, 0x0e, 0xf7, 0xa5, 0x43, 0x84, 0x96, 0x80, 0x8a, 0x1e, 0x30, 0xff, 0x0e, 0x94, 0xa9, 0xf8,
0x6e, 0xca, 0x9d, 0x73, 0xdd, 0xeb, 0x6b, 0x0e, 0x7e, 0x31, 0xa9, 0xe5, 0xd2, 0x7a, 0x21, 0x9e,
0xc0, 0xf5, 0x5a, 0xb2, 0x64, 0xd6, 0x7f, 0xe4, 0xa1, 0xa2, 0x67, 0xc8, 0xaf, 0xc3, 0x92, 0x08,
0xf1, 0x40, 0x26, 0xe6, 0xc7, 0x9c, 0xc4, 0x09, 0x2c, 0x06, 0x40, 0x06, 0x23, 0xda, 0xc3, 0xae,
0x49, 0x99, 0xb2, 0x28, 0xfe, 0x1e, 0x5c, 0xd2, 0xe0, 0x6e, 0x24, 0x22, 0x11, 0x08, 0x37, 0x16,
0x1b, 0x3d, 0x37, 0x0c, 0x45, 0x60, 0x9c, 0xd1, 0x49, 0xcd, 0xdc, 0x86, 0x05, 0xdd, 0xd4, 0x1a,
0xb8, 0x1d, 0x11, 0x9b, 0xda, 0xf4, 0x18, 0x8e, 0x7f, 0x0b, 0xca, 0xf4, 0x58, 0xa7, 0xe9, 0x9d,
0xae, 0x7c, 0x9a, 0xca, 0x92, 0xa9, 0xb5, 0x5c, 0x03, 0xd0, 0xbb, 0x81, 0x91, 0xba, 0x31, 0x21,
0x5f, 0x3d, 0x75, 0xfb, 0x28, 0x35, 0xc8, 0x30, 0xe1, 0xf8, 0x3c, 0x11, 0x08, 0xb4, 0x0f, 0x68,
0x29, 0x69, 0xf2, 0x45, 0x67, 0x0c, 0x67, 0xfd, 0x6d, 0x09, 0x4a, 0xb8, 0x91, 0x48, 0xdc, 0x93,
0x7d, 0x91, 0xde, 0x67, 0x68, 0xa5, 0x1d, 0xc3, 0xa1, 0x3b, 0x76, 0xf5, 0x75, 0x54, 0x4a, 0xa6,
0xcb, 0x20, 0x93, 0x68, 0xa4, 0x1c, 0x44, 0x72, 0xdf, 0x0f, 0x46, 0x94, 0xc6, 0x71, 0x4f, 0xa0,
0x71, 0xf9, 0xfb, 0x6e, 0x74, 0x20, 0x14, 0x59, 0x1f, 0x1c, 0x77, 0xca, 0xa1, 0x63, 0xfd, 0x93,
0x9a, 0xf9, 0x43, 0xb8, 0x9c, 0x69, 0x4a, 0x7c, 0x40, 0xca, 0xad, 0xeb, 0xfe, 0xa7, 0x91, 0x4c,
0x48, 0xd8, 0x13, 0xfd, 0x41, 0xe0, 0x2a, 0x31, 0x71, 0xa5, 0x73, 0x1a, 0x09, 0xff, 0x36, 0x5c,
0xcc, 0x34, 0xbf, 0x92, 0xd1, 0x41, 0x8c, 0xfb, 0xbe, 0xed, 0x99, 0xb2, 0xc3, 0x09, 0xad, 0xe8,
0x42, 0x3c, 0x71, 0xe8, 0x13, 0x65, 0x8d, 0x28, 0x53, 0x18, 0x55, 0xdb, 0xd5, 0x1b, 0xdb, 0x32,
0xb2, 0xea, 0xfa, 0x6e, 0x69, 0x1c, 0x8b, 0x11, 0x8b, 0xbe, 0x58, 0x8f, 0xb7, 0x3d, 0xaa, 0x84,
0xd4, 0x9d, 0x11, 0x82, 0x5f, 0x05, 0xe8, 0xba, 0x4a, 0xbc, 0x76, 0x8f, 0x5f, 0x44, 0x41, 0x53,
0xe8, 0x9a, 0xe0, 0x08, 0x83, 0xc9, 0x55, 0x20, 0x3b, 0x6e, 0xd0, 0x52, 0x32, 0x72, 0xbb, 0x62,
0xd7, 0x55, 0xbd, 0x66, 0x57, 0x27, 0x57, 0x93, 0x78, 0x1c, 0x2d, 0xa6, 0xf2, 0x1f, 0xc9, 0x50,
0x34, 0x7b, 0x7a, 0xb4, 0x09, 0x6c, 0xef, 0x00, 0x8c, 0xd4, 0x0f, 0x7d, 0xce, 0x1a, 0xd5, 0x1d,
0x59, 0x0e, 0xa3, 0xd3, 0x5d, 0x11, 0x7a, 0x7e, 0xd8, 0xdd, 0x34, 0x1a, 0xc7, 0xf2, 0x88, 0x6c,
0x29, 0x37, 0x52, 0xc2, 0x4b, 0x91, 0x94, 0x35, 0x10, 0x24, 0x3c, 0x56, 0xb4, 0xff, 0x27, 0x0f,
0x8d, 0xcc, 0xad, 0xdb, 0xcf, 0xf0, 0xa6, 0x10, 0xfd, 0x36, 0x5a, 0x1a, 0x5c, 0x10, 0xad, 0x8d,
0x29, 0x8c, 0xcb, 0x65, 0x2e, 0x05, 0xb1, 0x55, 0x6b, 0x5e, 0x06, 0xf3, 0xa5, 0x6e, 0x09, 0xed,
0x3b, 0x26, 0xcf, 0x6e, 0x40, 0xf5, 0x45, 0x78, 0x10, 0xca, 0xd7, 0xa1, 0xf6, 0xdf, 0x74, 0xf5,
0x3b, 0x56, 0xec, 0x4e, 0x6e, 0x67, 0x8b, 0xf6, 0x4f, 0x4a, 0x13, 0xaf, 0x24, 0x1e, 0x41, 0x45,
0xc7, 0xa1, 0x14, 0x22, 0x4d, 0x5f, 0x6b, 0x67, 0x89, 0x4d, 0x61, 0x35, 0x83, 0x72, 0x0c, 0x33,
0x06, 0x88, 0xe9, 0x53, 0xa0, 0xc2, 0xcc, 0x02, 0xf0, 0x98, 0xa0, 0xc4, 0x80, 0x8e, 0xbd, 0x86,
0x4b, 0x25, 0x58, 0x3f, 0xce, 0xc3, 0xca, 0x2c, 0x12, 0x8c, 0xd7, 0xda, 0x63, 0x8f, 0x15, 0x12,
0x90, 0xb7, 0x26, 0xde, 0xe0, 0x15, 0x68, 0x36, 0xb7, 0xce, 0x38, 0x88, 0xf1, 0x17, 0x79, 0xf6,
0xa7, 0x79, 0x58, 0x9e, 0x9a, 0x73, 0x26, 0x18, 0x02, 0xa8, 0x68, 0xcd, 0xd2, 0x77, 0xeb, 0xe9,
0x6d, 0xa7, 0xae, 0xcf, 0x91, 0x37, 0x8a, 0xf5, 0xf5, 0xd1, 0xa6, 0x7e, 0xc1, 0xc9, 0x4a, 0x18,
0xc5, 0xe0, 0xae, 0xa1, 0x95, 0xef, 0x0a, 0x56, 0xc6, 0xdc, 0x4c, 0x07, 0x61, 0x06, 0x53, 0xa1,
0xbc, 0xcf, 0x58, 0x02, 0x56, 0xa5, 0x3b, 0xfb, 0xe1, 0x20, 0xf0, 0x3b, 0x08, 0xd6, 0x6c, 0x07,
0xce, 0xcf, 0x18, 0x37, 0x8d, 0xe4, 0xa5, 0x19, 0xd5, 0x12, 0xc0, 0xe6, 0xcb, 0x64, 0x2c, 0x2c,
0x8f, 0xe9, 0xf1, 0xe6, 0xcb, 0x0d, 0x4a, 0x90, 0xcd, 0x8d, 0x98, 0x3e, 0x13, 0x2f, 0x31, 0xa3,
0x8a, 0x59, 0xd1, 0x7e, 0x00, 0x17, 0xf6, 0x7a, 0x91, 0x70, 0xbd, 0x4d, 0x21, 0x06, 0x01, 0x2a,
0x9b, 0x7b, 0x1c, 0x48, 0xd7, 0x9b, 0x51, 0x21, 0x5c, 0x81, 0xb2, 0xeb, 0x79, 0x91, 0x5e, 0xdf,
0xba, 0xa3, 0x01, 0xfb, 0x07, 0x70, 0x51, 0x0b, 0xd0, 0xbd, 0x7c, 0x38, 0x14, 0x43, 0xf1, 0x28,
0x54, 0xd1, 0xb1, 0xae, 0xf1, 0x26, 0x4f, 0x37, 0x35, 0x8d, 0x11, 0x37, 0x85, 0x27, 0x3b, 0x40,
0x5f, 0xa9, 0x7f, 0x48, 0x61, 0xfb, 0x7f, 0x4b, 0x00, 0x3b, 0xe9, 0x8b, 0xd3, 0x19, 0xa7, 0x76,
0x56, 0x34, 0x34, 0x55, 0xed, 0x2f, 0x9e, 0xb5, 0xda, 0xcf, 0xdf, 0x4b, 0xc3, 0x6c, 0xfd, 0x16,
0x65, 0xf2, 0x49, 0xdf, 0x68, 0x4c, 0x13, 0xc1, 0xf5, 0xf8, 0x2d, 0x71, 0x79, 0xf2, 0x96, 0xf8,
0xda, 0xf4, 0x93, 0x92, 0x09, 0x73, 0x32, 0x4a, 0x5a, 0xab, 0x63, 0x49, 0xab, 0x05, 0x35, 0x5c,
0x13, 0x19, 0x06, 0xc7, 0x49, 0x81, 0x3a, 0x81, 0xf9, 0x5d, 0x28, 0x2b, 0x7a, 0xa3, 0x5b, 0x23,
0xed, 0x9f, 0x8c, 0xc7, 0x46, 0xcf, 0x96, 0xc9, 0x8a, 0x68, 0x5a, 0xb4, 0x4d, 0x7e, 0x6c, 0xde,
0x81, 0x68, 0x67, 0x50, 0x73, 0x32, 0x18, 0xbe, 0x0a, 0xdc, 0x0f, 0x63, 0xe5, 0x06, 0x81, 0xf0,
0xd6, 0x8f, 0x37, 0xc5, 0xbe, 0x3b, 0x0c, 0x14, 0x39, 0xa0, 0x9a, 0x33, 0xa3, 0xc5, 0xfe, 0x97,
0xd1, 0xfb, 0xa7, 0x3a, 0x94, 0xdb, 0x6e, 0xec, 0x77, 0xf4, 0x4d, 0xab, 0xf1, 0xcd, 0xfa, 0x4a,
0x4c, 0x49, 0x4f, 0xb2, 0x02, 0xa6, 0x13, 0xb1, 0xc0, 0xc4, 0x61, 0x09, 0x60, 0xf4, 0xa2, 0x98,
0x95, 0xf0, 0x10, 0x24, 0x3b, 0xa1, 0x2f, 0x5a, 0x89, 0x95, 0x2a, 0x1b, 0x5e, 0xfa, 0x84, 0xa5,
0x8a, 0x3d, 0x90, 0x91, 0x65, 0x35, 0xa4, 0x09, 0xa5, 0x12, 0xba, 0x96, 0x43, 0x9e, 0x90, 0x01,
0x8a, 0x49, 0x1e, 0x48, 0xb2, 0x06, 0x46, 0xfc, 0x89, 0x50, 0x5d, 0x8c, 0x89, 0xa9, 0xb4, 0xbe,
0x80, 0x47, 0x64, 0xbc, 0x41, 0x97, 0x78, 0xd0, 0x20, 0xb5, 0xdd, 0x58, 0xb0, 0x15, 0xfb, 0xf7,
0x47, 0xb3, 0x7a, 0x27, 0x0d, 0xc4, 0xe7, 0xd1, 0x87, 0x93, 0x42, 0xf5, 0x47, 0xb0, 0x1c, 0x89,
0x4f, 0x86, 0xfe, 0xd8, 0x93, 0xc5, 0xe2, 0xe9, 0x97, 0x72, 0xd3, 0x1c, 0xf6, 0x21, 0x2c, 0x27,
0xc0, 0x2b, 0x5f, 0xf5, 0x28, 0x2b, 0xe6, 0x77, 0x33, 0x6f, 0x2a, 0xf3, 0x26, 0x32, 0x3c, 0x41,
0xe4, 0xe8, 0x0d, 0x65, 0x5a, 0x8d, 0x2c, 0xcc, 0x51, 0x8d, 0xb4, 0xff, 0xbd, 0x92, 0x49, 0x8c,
0x75, 0x6a, 0xe2, 0xa5, 0xa9, 0xc9, 0xb4, 0xdd, 0x18, 0x15, 0x18, 0x0b, 0x67, 0x29, 0x30, 0xce,
0xba, 0x0e, 0xfb, 0x2e, 0xc6, 0x9d, 0xa4, 0x6a, 0x2f, 0xe7, 0x28, 0x9e, 0x8e, 0xd1, 0xf2, 0x75,
0xba, 0x27, 0x70, 0x5b, 0xfa, 0x7e, 0xb5, 0x3c, 0xf3, 0x85, 0x73, 0xf6, 0x42, 0xc0, 0x50, 0x3a,
0x19, 0xae, 0xcc, 0xc1, 0xac, 0xcc, 0x3a, 0x98, 0x98, 0x25, 0x9a, 0x23, 0x9b, 0xc2, 0xba, 0xd6,
0xac, 0xbf, 0x13, 0xf1, 0xf4, 0x34, 0xb9, 0xe6, 0x4c, 0xe1, 0xd1, 0xc4, 0xf6, 0x87, 0x81, 0xf2,
0x4d, 0x39, 0x55, 0x03, 0x93, 0x8f, 0xf0, 0xeb, 0xd3, 0x8f, 0xf0, 0x3f, 0x00, 0x88, 0x05, 0x5a,
0xd4, 0x4d, 0xbf, 0xa3, 0xcc, 0x2d, 0xec, 0xd5, 0x93, 0xe6, 0x66, 0x8a, 0xc0, 0x19, 0x0e, 0x1c,
0x7f, 0xdf, 0x3d, 0xda, 0xc0, 0x18, 0xb0, 0xb9, 0x48, 0x19, 0x68, 0x0a, 0x4f, 0x9a, 0xab, 0xa5,
0x69, 0x73, 0x75, 0x17, 0xca, 0x71, 0x47, 0x0e, 0x04, 0xbd, 0x22, 0x3e, 0x79, 0x7f, 0x57, 0x5b,
0x48, 0xe4, 0x68, 0x5a, 0x2a, 0xbf, 0xa0, 0xc7, 0x90, 0x11, 0xbd, 0x1f, 0xae, 0x3b, 0x09, 0x68,
0x79, 0x50, 0x31, 0xe5, 0xd2, 0x19, 0x69, 0x2f, 0x55, 0x5a, 0x0a, 0x99, 0xf7, 0x43, 0xe9, 0x3b,
0x9d, 0x62, 0xf6, 0x9d, 0xce, 0x35, 0x68, 0x44, 0x99, 0x2b, 0x00, 0xf3, 0x38, 0x2b, 0x83, 0xb2,
0x3f, 0x82, 0x32, 0x8d, 0x07, 0xdd, 0xa7, 0x5e, 0x4a, 0x1d, 0x41, 0xe1, 0xc0, 0x59, 0x9e, 0xaf,
0x00, 0x8b, 0x85, 0xda, 0xd9, 0xdf, 0xeb, 0x89, 0x96, 0xdb, 0xa7, 0xf4, 0x80, 0x15, 0x78, 0x13,
0x56, 0x34, 0x6d, 0x3c, 0xde, 0x42, 0x7e, 0x3e, 0xf0, 0xdb, 0x91, 0x1b, 0x1d, 0xb3, 0x92, 0xfd,
0x01, 0xdd, 0x1b, 0x25, 0x4a, 0xd3, 0x48, 0xff, 0xec, 0xa1, 0x6d, 0xa1, 0x27, 0x22, 0x34, 0xae,
0xfa, 0x56, 0xcf, 0x44, 0xde, 0xfa, 0x85, 0x00, 0x85, 0xc7, 0xac, 0x68, 0xbf, 0xc2, 0x40, 0x6d,
0xe4, 0x8a, 0x7e, 0x66, 0x67, 0xca, 0x5e, 0xcf, 0x04, 0x2a, 0xe3, 0x4f, 0x02, 0xf2, 0xf3, 0x3e,
0x09, 0xb0, 0x9f, 0xc0, 0x39, 0x67, 0xdc, 0x90, 0xf2, 0xf7, 0xa0, 0x2a, 0x07, 0x59, 0x39, 0x6f,
0xd2, 0xbd, 0x84, 0xdc, 0xfe, 0x83, 0x3c, 0x2c, 0x6c, 0x87, 0x4a, 0x44, 0xa1, 0x1b, 0x3c, 0x0e,
0xdc, 0x2e, 0x7f, 0x37, 0xb1, 0x44, 0xb3, 0xf3, 0xd2, 0x2c, 0xed, 0xb8, 0x51, 0x7a, 0x6e, 0xca,
0x82, 0xfc, 0x02, 0x2c, 0x0b, 0xcf, 0x57, 0x32, 0xd2, 0xe1, 0x59, 0xf2, 0x32, 0x63, 0x05, 0x98,
0x46, 0xb7, 0x48, 0xed, 0xf7, 0xf4, 0x36, 0x37, 0x61, 0x65, 0x0c, 0x9b, 0xc4, 0x5e, 0x05, 0xfb,
0xdf, 0xca, 0x49, 0xd4, 0xf1, 0xd2, 0xbc, 0xcc, 0x88, 0xa4, 0x54, 0xa3, 0xb2, 0xaf, 0x86, 0x32,
0xff, 0xfb, 0x29, 0xcc, 0xf1, 0xbf, 0x9f, 0x0f, 0x46, 0xff, 0xfb, 0xd1, 0xe6, 0xfe, 0xad, 0x99,
0x3e, 0x84, 0x2e, 0xa7, 0x4d, 0xd8, 0xd8, 0x12, 0x99, 0x3f, 0x01, 0xdd, 0x36, 0xb9, 0x42, 0x69,
0xe6, 0xa6, 0x4f, 0xf8, 0x78, 0x7d, 0x97, 0x77, 0x7f, 0xf2, 0xbd, 0xe9, 0x7c, 0x0f, 0x3f, 0xa6,
0xe2, 0x27, 0x38, 0x73, 0xfc, 0xf4, 0x60, 0x22, 0x2c, 0xaf, 0xcd, 0xac, 0xf9, 0x9c, 0xf2, 0xa7,
0x98, 0x07, 0x50, 0xed, 0xf9, 0xb1, 0x92, 0xd1, 0x31, 0x85, 0x26, 0xd3, 0x0f, 0xcb, 0x33, 0xab,
0xb5, 0xa5, 0x09, 0xe9, 0x46, 0x3f, 0xe1, 0xb2, 0xba, 0x00, 0xa3, 0x55, 0x9c, 0xb2, 0x26, 0x5f,
0xe2, 0x4f, 0x58, 0x17, 0xa1, 0x12, 0x0f, 0xdb, 0xa3, 0x3a, 0xbe, 0x81, 0xac, 0x23, 0xb0, 0xa6,
0x3c, 0xf1, 0xae, 0x88, 0xf4, 0xf8, 0xd0, 0xba, 0x26, 0xf5, 0x7e, 0xd3, 0x7d, 0x0a, 0xf3, 0x0f,
0xb2, 0xdb, 0xa3, 0x55, 0xe8, 0xda, 0x09, 0x6b, 0x9c, 0x4a, 0xce, 0xec, 0x93, 0x75, 0x1f, 0x1a,
0x99, 0xa9, 0xa3, 0x85, 0x1c, 0x86, 0x9e, 0x4c, 0x0a, 0x8b, 0xf8, 0xad, 0x1f, 0xc3, 0x7b, 0x49,
0x69, 0x91, 0xbe, 0x6f, 0xfe, 0x5e, 0x11, 0x96, 0xc6, 0xd5, 0x85, 0x4a, 0xac, 0xda, 0x18, 0xed,
0x04, 0x9e, 0xae, 0xc1, 0xae, 0xa3, 0x83, 0xea, 0x44, 0xc3, 0x7e, 0x3b, 0xd6, 0x91, 0x1b, 0xa5,
0x97, 0x0c, 0x9b, 0x76, 0x75, 0x40, 0x47, 0x88, 0x65, 0x6c, 0xda, 0x92, 0x7d, 0xc1, 0xae, 0x65,
0xdf, 0x15, 0xbf, 0x93, 0xbc, 0x40, 0xa6, 0x30, 0xea, 0x21, 0xc6, 0x7b, 0x2d, 0xa1, 0xd8, 0x1a,
0xa6, 0x3d, 0xad, 0xbd, 0x51, 0xb4, 0xc4, 0x7e, 0x80, 0x36, 0x58, 0x97, 0xa9, 0xd9, 0x80, 0xd7,
0xcd, 0x93, 0xad, 0x1f, 0x15, 0xf8, 0x62, 0x26, 0x1b, 0xfa, 0x69, 0x81, 0xaf, 0xc0, 0xb9, 0xf5,
0x61, 0xe8, 0x05, 0xc2, 0x4b, 0xb1, 0x7f, 0x4c, 0xd8, 0x67, 0xe3, 0x75, 0x1c, 0xf6, 0x29, 0x5a,
0xea, 0xf3, 0xcf, 0xa6, 0xeb, 0x33, 0xec, 0x77, 0x27, 0x5b, 0x52, 0x49, 0x3f, 0xc9, 0xca, 0x4f,
0xe9, 0x7f, 0x84, 0x49, 0x5b, 0xbd, 0x35, 0x6c, 0x9b, 0xec, 0xe9, 0x37, 0x4a, 0xfc, 0x22, 0x2c,
0x1b, 0xaa, 0xcc, 0x14, 0x7e, 0xb3, 0xc4, 0xcf, 0xc3, 0xd2, 0x9a, 0xde, 0x37, 0xb3, 0x36, 0xec,
0xb7, 0x4a, 0x38, 0x19, 0xba, 0xeb, 0xfb, 0xed, 0x12, 0x5f, 0x86, 0x85, 0xb4, 0x4e, 0x83, 0x2b,
0xfc, 0x63, 0x12, 0x9d, 0xa2, 0xd8, 0xef, 0x94, 0x6e, 0xfe, 0x79, 0x1e, 0x96, 0xc6, 0x2d, 0x37,
0x2e, 0x61, 0x20, 0xc3, 0xae, 0xd2, 0x0f, 0xac, 0x17, 0xa1, 0x1e, 0xf7, 0x64, 0xa4, 0x08, 0xa4,
0x3a, 0x7c, 0x48, 0xb7, 0x74, 0x3a, 0xe9, 0xd4, 0x05, 0x3a, 0xfd, 0xc4, 0x40, 0xb9, 0x5d, 0xd6,
0xc0, 0x7d, 0xf1, 0xb0, 0xfb, 0x52, 0x1a, 0x45, 0xd3, 0x6d, 0x61, 0x72, 0x1b, 0xc3, 0x2a, 0x48,
0x3a, 0x8c, 0x02, 0x1d, 0x4d, 0x8b, 0xbe, 0xeb, 0x07, 0xfa, 0x25, 0xe5, 0xa0, 0x87, 0xf9, 0x64,
0x5d, 0x63, 0xe5, 0xc7, 0xbe, 0x7e, 0xb3, 0x68, 0xfc, 0xa4, 0x87, 0xe3, 0x48, 0x55, 0x90, 0x89,
0xf5, 0x9b, 0x7f, 0xff, 0xf9, 0xd5, 0xfc, 0x67, 0x9f, 0x5f, 0xcd, 0xff, 0xe7, 0xe7, 0x57, 0xf3,
0x9f, 0x7e, 0x71, 0x35, 0xf7, 0xd9, 0x17, 0x57, 0x73, 0xff, 0xfa, 0xc5, 0xd5, 0xdc, 0x47, 0x6c,
0xf2, 0x4f, 0x98, 0xed, 0x0a, 0x1d, 0xae, 0xbb, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x61, 0xbb,
0x13, 0x6c, 0x9f, 0x39, 0x00, 0x00,
0xf5, 0x7a, 0x67, 0xdb, 0x33, 0xfe, 0xec, 0xcc, 0x0e, 0xcc, 0x78, 0xfa, 0x63, 0x4f, 0xb7, 0xfc,
0xe9, 0x9e, 0xac, 0xb6, 0xcd, 0x8e, 0x00, 0x4d, 0x56, 0x65, 0x74, 0x55, 0x4e, 0x67, 0x65, 0xd4,
0x64, 0x46, 0xb5, 0xbb, 0x57, 0x42, 0x1a, 0x3e, 0xcb, 0x79, 0x58, 0x84, 0x38, 0x21, 0x2d, 0x27,
0x2e, 0x5c, 0x11, 0x20, 0x21, 0x2e, 0x08, 0x81, 0xc4, 0x81, 0x11, 0x5c, 0x56, 0x42, 0x02, 0x34,
0x73, 0xe4, 0xc6, 0x19, 0x21, 0xf4, 0x5e, 0x44, 0x66, 0x65, 0x7d, 0xba, 0x5d, 0x3d, 0xbb, 0xa7,
0xca, 0xf7, 0xe2, 0xbd, 0x17, 0xbf, 0x17, 0xef, 0x17, 0x51, 0xf0, 0xda, 0xe0, 0xa0, 0x7b, 0x2b,
0xf0, 0xdb, 0xb7, 0x06, 0xed, 0x5b, 0x7d, 0xe9, 0x89, 0xe0, 0xd6, 0x20, 0x92, 0x4a, 0xc6, 0x1a,
0x88, 0x57, 0x09, 0xe2, 0x8b, 0x6e, 0x78, 0xac, 0x8e, 0x07, 0x62, 0x95, 0xb0, 0xd6, 0x95, 0xae,
0x94, 0xdd, 0x40, 0x68, 0xd2, 0xf6, 0x70, 0xff, 0x56, 0xac, 0xa2, 0x61, 0x47, 0x69, 0x62, 0xfb,
0x1f, 0x8a, 0x70, 0xb1, 0xd5, 0x77, 0x23, 0xb5, 0x1e, 0xc8, 0xce, 0x41, 0x2b, 0x74, 0x07, 0x71,
0x4f, 0xaa, 0x75, 0x37, 0x16, 0xfc, 0x75, 0xa8, 0xb4, 0x11, 0x19, 0x37, 0xf3, 0xd7, 0x8a, 0x37,
0x1a, 0xb7, 0x57, 0x56, 0xc7, 0x04, 0xaf, 0x12, 0x87, 0x63, 0x68, 0xf8, 0x9b, 0x50, 0xf5, 0x84,
0x72, 0xfd, 0x20, 0x6e, 0x16, 0xae, 0xe5, 0x6f, 0x34, 0x6e, 0x5f, 0x5a, 0xd5, 0x1d, 0xaf, 0x26,
0x1d, 0xaf, 0xb6, 0xa8, 0x63, 0x27, 0xa1, 0xe3, 0x77, 0xa0, 0xb6, 0xef, 0x07, 0xe2, 0x91, 0x38,
0x8e, 0x9b, 0xc5, 0xd3, 0x79, 0x52, 0x42, 0x7e, 0x1f, 0x96, 0xc4, 0x91, 0x8a, 0x5c, 0x47, 0x04,
0xae, 0xf2, 0x65, 0x18, 0x37, 0x4b, 0x34, 0xba, 0x4b, 0x13, 0xa3, 0x4b, 0xda, 0x9d, 0x09, 0x72,
0x7e, 0x0d, 0x1a, 0xb2, 0xfd, 0x89, 0xe8, 0xa8, 0xbd, 0xe3, 0x81, 0x88, 0x9b, 0xe5, 0x6b, 0xc5,
0x1b, 0x75, 0x27, 0x8b, 0xe2, 0x3f, 0x80, 0x46, 0x47, 0x06, 0x81, 0xe8, 0x68, 0xf9, 0x95, 0xd3,
0x87, 0x96, 0xa5, 0xe5, 0x77, 0xe1, 0x42, 0x24, 0xfa, 0xf2, 0x50, 0x78, 0x1b, 0x29, 0x96, 0xe6,
0x57, 0xa3, 0x6e, 0x66, 0x37, 0xf2, 0x35, 0x58, 0x8c, 0xcc, 0xf8, 0x1e, 0xfb, 0xe1, 0x41, 0xdc,
0xac, 0xd2, 0x94, 0x2e, 0x9f, 0x30, 0x25, 0xa4, 0x71, 0xc6, 0x39, 0xec, 0x7f, 0x5d, 0x83, 0x32,
0x6d, 0x08, 0x5f, 0x82, 0x82, 0xef, 0x35, 0xf3, 0xd7, 0xf2, 0x37, 0xea, 0x4e, 0xc1, 0xf7, 0xf8,
0x2d, 0xa8, 0xec, 0xfb, 0x22, 0xf0, 0x5e, 0xb9, 0x2f, 0x86, 0x8c, 0x3f, 0x80, 0x85, 0x48, 0xc4,
0x2a, 0xf2, 0xcd, 0xfc, 0xf5, 0xd6, 0x7c, 0x73, 0xd6, 0xee, 0xaf, 0x3a, 0x19, 0x42, 0x67, 0x8c,
0x0d, 0xd7, 0xb9, 0xd3, 0xf3, 0x03, 0x2f, 0x12, 0xe1, 0xb6, 0xa7, 0x77, 0xa9, 0xee, 0x64, 0x51,
0xfc, 0x06, 0x9c, 0x6b, 0xbb, 0x9d, 0x83, 0x6e, 0x24, 0x87, 0x21, 0x2e, 0x89, 0x8c, 0x9a, 0x65,
0x1a, 0xf6, 0x24, 0x9a, 0xbf, 0x01, 0x65, 0x37, 0xf0, 0xbb, 0x21, 0xed, 0xc5, 0xd2, 0x6d, 0x6b,
0xe6, 0x58, 0xd6, 0x90, 0xc2, 0xd1, 0x84, 0x7c, 0x0b, 0x16, 0x0f, 0x45, 0xa4, 0xfc, 0x8e, 0x1b,
0x10, 0xbe, 0x59, 0x25, 0x4e, 0x7b, 0x26, 0xe7, 0xf3, 0x2c, 0xa5, 0x33, 0xce, 0xc8, 0xb7, 0x01,
0x62, 0x3c, 0x20, 0xa4, 0xe7, 0xcd, 0x06, 0x2d, 0xc6, 0xb7, 0x67, 0x8a, 0xd9, 0x90, 0xa1, 0x12,
0xa1, 0x5a, 0x6d, 0xa5, 0xe4, 0x5b, 0x39, 0x27, 0xc3, 0xcc, 0xdf, 0x82, 0x92, 0x12, 0x47, 0xaa,
0xb9, 0x74, 0xca, 0x8a, 0x26, 0x42, 0xf6, 0xc4, 0x91, 0xda, 0xca, 0x39, 0xc4, 0x80, 0x8c, 0x78,
0x00, 0x9a, 0xe7, 0xe6, 0x60, 0x7c, 0xe8, 0x07, 0x02, 0x19, 0x91, 0x81, 0xbf, 0x0b, 0x95, 0xc0,
0x3d, 0x96, 0x43, 0xd5, 0x64, 0xc4, 0xfa, 0x2b, 0xa7, 0xb2, 0x3e, 0x26, 0xd2, 0xad, 0x9c, 0x63,
0x98, 0xf8, 0x5d, 0x28, 0x7a, 0xfe, 0x61, 0x73, 0x99, 0x78, 0xaf, 0x9d, 0xca, 0xbb, 0xe9, 0x1f,
0x6e, 0xe5, 0x1c, 0x24, 0xe7, 0x1b, 0x50, 0x6b, 0x4b, 0x79, 0xd0, 0x77, 0xa3, 0x83, 0x26, 0x27,
0xd6, 0x6f, 0x9d, 0xca, 0xba, 0x6e, 0x88, 0xb7, 0x72, 0x4e, 0xca, 0x88, 0x53, 0xf6, 0x3b, 0x32,
0x6c, 0x9e, 0x9f, 0x63, 0xca, 0xdb, 0x1d, 0x19, 0xe2, 0x94, 0x91, 0x01, 0x19, 0x03, 0x3f, 0x3c,
0x68, 0xae, 0xcc, 0xc1, 0x88, 0x67, 0x07, 0x19, 0x91, 0x01, 0x87, 0xed, 0xb9, 0xca, 0x3d, 0xf4,
0xc5, 0xcb, 0xe6, 0x85, 0x39, 0x86, 0xbd, 0x69, 0x88, 0x71, 0xd8, 0x09, 0x23, 0x0a, 0x49, 0x0e,
0x66, 0xf3, 0xe2, 0x1c, 0x42, 0x92, 0x33, 0x8d, 0x42, 0x12, 0x46, 0xfe, 0x5b, 0xb0, 0xbc, 0x2f,
0x5c, 0x35, 0x8c, 0x84, 0x37, 0x32, 0x73, 0x97, 0x48, 0xda, 0xea, 0xe9, 0x7b, 0x3f, 0xc9, 0xb5,
0x95, 0x73, 0xa6, 0x45, 0xf1, 0x77, 0xa0, 0x1c, 0xb8, 0x4a, 0x1c, 0x35, 0x9b, 0x24, 0xd3, 0x7e,
0x85, 0x52, 0x28, 0x71, 0xb4, 0x95, 0x73, 0x34, 0x0b, 0xff, 0x75, 0x38, 0xa7, 0xdc, 0x76, 0x20,
0x76, 0xf6, 0x0d, 0x41, 0xdc, 0xfc, 0x25, 0x92, 0xf2, 0xfa, 0xe9, 0xea, 0x3c, 0xce, 0xb3, 0x95,
0x73, 0x26, 0xc5, 0xe0, 0xa8, 0x08, 0xd5, 0xb4, 0xe6, 0x18, 0x15, 0xc9, 0xc3, 0x51, 0x11, 0x0b,
0x7f, 0x0c, 0x0d, 0xfa, 0xd8, 0x90, 0xc1, 0xb0, 0x1f, 0x36, 0x2f, 0x93, 0x84, 0x1b, 0xaf, 0x96,
0xa0, 0xe9, 0xb7, 0x72, 0x4e, 0x96, 0x1d, 0x37, 0x91, 0x40, 0x47, 0xbe, 0x6c, 0x5e, 0x99, 0x63,
0x13, 0xf7, 0x0c, 0x31, 0x6e, 0x62, 0xc2, 0x88, 0x47, 0xef, 0xa5, 0xef, 0x75, 0x85, 0x6a, 0x7e,
0x63, 0x8e, 0xa3, 0xf7, 0x82, 0x48, 0xf1, 0xe8, 0x69, 0x26, 0xeb, 0x47, 0xb0, 0x90, 0x35, 0xae,
0x9c, 0x43, 0x29, 0x12, 0xae, 0x36, 0xec, 0x35, 0x87, 0xbe, 0x11, 0x27, 0x3c, 0x5f, 0x91, 0x61,
0xaf, 0x39, 0xf4, 0xcd, 0x2f, 0x42, 0x45, 0x3b, 0x19, 0xb2, 0xdb, 0x35, 0xc7, 0x40, 0x48, 0xeb,
0x45, 0x6e, 0xb7, 0x59, 0xd2, 0xb4, 0xf8, 0x8d, 0xb4, 0x5e, 0x24, 0x07, 0x3b, 0x21, 0xd9, 0xdd,
0x9a, 0x63, 0x20, 0xeb, 0xb3, 0x3b, 0x50, 0x35, 0x03, 0xb3, 0xfe, 0x34, 0x0f, 0x15, 0x6d, 0x17,
0xf8, 0x7d, 0x28, 0xc7, 0xea, 0x38, 0x10, 0x34, 0x86, 0xa5, 0xdb, 0xdf, 0x99, 0xc3, 0x96, 0xac,
0xb6, 0x90, 0xc1, 0xd1, 0x7c, 0xb6, 0x03, 0x65, 0x82, 0x79, 0x15, 0x8a, 0x8e, 0x7c, 0xc9, 0x72,
0x1c, 0xa0, 0xa2, 0xd7, 0x9c, 0xe5, 0x11, 0xb9, 0xe9, 0x1f, 0xb2, 0x02, 0x22, 0xb7, 0x84, 0xeb,
0x89, 0x88, 0x15, 0xf9, 0x22, 0xd4, 0x93, 0xd5, 0x8d, 0x59, 0x89, 0x33, 0x58, 0xc8, 0xec, 0x5b,
0xcc, 0xca, 0xd6, 0xff, 0x94, 0xa0, 0x84, 0xc7, 0x98, 0xbf, 0x06, 0x8b, 0xca, 0x8d, 0xba, 0x42,
0x47, 0x32, 0xdb, 0x89, 0x0b, 0x1c, 0x47, 0xf2, 0x77, 0x93, 0x39, 0x14, 0x68, 0x0e, 0xdf, 0x7e,
0xa5, 0x79, 0x18, 0x9b, 0x41, 0xc6, 0x99, 0x16, 0xe7, 0x73, 0xa6, 0x0f, 0xa1, 0x86, 0x56, 0xa9,
0xe5, 0xff, 0x48, 0xd0, 0xd2, 0x2f, 0xdd, 0xbe, 0xf9, 0xea, 0x2e, 0xb7, 0x0d, 0x87, 0x93, 0xf2,
0xf2, 0x6d, 0xa8, 0x77, 0xdc, 0xc8, 0xa3, 0xc1, 0xd0, 0x6e, 0x2d, 0xdd, 0xfe, 0xee, 0xab, 0x05,
0x6d, 0x24, 0x2c, 0xce, 0x88, 0x9b, 0xef, 0x40, 0xc3, 0x13, 0x71, 0x27, 0xf2, 0x07, 0x64, 0xa5,
0xb4, 0x4b, 0xfd, 0xde, 0xab, 0x85, 0x6d, 0x8e, 0x98, 0x9c, 0xac, 0x04, 0x7e, 0x05, 0xea, 0x51,
0x6a, 0xa6, 0xaa, 0xe4, 0xe7, 0x47, 0x08, 0xfb, 0x2d, 0xa8, 0x25, 0xf3, 0xe1, 0x0b, 0x50, 0xc3,
0xdf, 0xa7, 0x32, 0x14, 0x2c, 0x87, 0x7b, 0x8b, 0x50, 0xab, 0xef, 0x06, 0x01, 0xcb, 0xf3, 0x25,
0x00, 0x04, 0x9f, 0x08, 0xcf, 0x1f, 0xf6, 0x59, 0xc1, 0xfe, 0xd5, 0x44, 0x5b, 0x6a, 0x50, 0xda,
0x75, 0xbb, 0xc8, 0xb1, 0x00, 0xb5, 0xc4, 0xea, 0xb2, 0x3c, 0xf2, 0x6f, 0xba, 0x71, 0xaf, 0x2d,
0xdd, 0xc8, 0x63, 0x05, 0xde, 0x80, 0xea, 0x5a, 0xd4, 0xe9, 0xf9, 0x87, 0x82, 0x15, 0xed, 0x5b,
0xd0, 0xc8, 0x8c, 0x17, 0x45, 0x98, 0x4e, 0xeb, 0x50, 0x5e, 0xf3, 0x3c, 0xe1, 0xb1, 0x3c, 0x32,
0x98, 0x09, 0xb2, 0x82, 0xfd, 0x5d, 0xa8, 0xa7, 0xab, 0x85, 0xe4, 0xe8, 0x7f, 0x59, 0x0e, 0xbf,
0x10, 0xcd, 0xf2, 0xa8, 0x95, 0xdb, 0x61, 0xe0, 0x87, 0x82, 0x15, 0xac, 0x8f, 0x49, 0x55, 0xf9,
0xaf, 0x8d, 0x1f, 0x88, 0xeb, 0xaf, 0x72, 0x90, 0xe3, 0xa7, 0xe1, 0x72, 0x66, 0x7e, 0x8f, 0x7d,
0x1a, 0x5c, 0x0d, 0x4a, 0x9b, 0x52, 0xc5, 0x2c, 0x6f, 0xfd, 0x77, 0x01, 0x6a, 0x89, 0x5f, 0xe4,
0x0c, 0x8a, 0xc3, 0x28, 0x30, 0x0a, 0x8d, 0x9f, 0x7c, 0x05, 0xca, 0xca, 0x57, 0x46, 0x8d, 0xeb,
0x8e, 0x06, 0x30, 0xe4, 0xca, 0xee, 0x6c, 0x91, 0xda, 0x26, 0xb7, 0xca, 0xef, 0xbb, 0x5d, 0xb1,
0xe5, 0xc6, 0x3d, 0xd2, 0xc7, 0xba, 0x33, 0x42, 0x20, 0xff, 0xbe, 0x7b, 0x88, 0x3a, 0x47, 0xed,
0x3a, 0x18, 0xcb, 0xa2, 0xf8, 0x1d, 0x28, 0xe1, 0x04, 0x8d, 0xd2, 0xfc, 0xf2, 0xc4, 0x84, 0x51,
0x4d, 0x76, 0x23, 0x81, 0xdb, 0xb3, 0x8a, 0xa1, 0xb4, 0x43, 0xc4, 0xfc, 0x3a, 0x2c, 0xe9, 0x43,
0xb8, 0x43, 0x41, 0xf6, 0xb6, 0x47, 0xc1, 0x58, 0xdd, 0x99, 0xc0, 0xf2, 0x35, 0x5c, 0x4e, 0x57,
0x89, 0x66, 0x6d, 0x0e, 0xfd, 0x4e, 0x16, 0x67, 0xb5, 0x85, 0x2c, 0x8e, 0xe6, 0xb4, 0xef, 0xe1,
0x9a, 0xba, 0x4a, 0xe0, 0x36, 0x3f, 0xe8, 0x0f, 0xd4, 0xb1, 0x56, 0x9a, 0x87, 0x42, 0x75, 0x7a,
0x7e, 0xd8, 0x65, 0x79, 0xbd, 0xc4, 0xb8, 0x89, 0x44, 0x12, 0x45, 0x32, 0x62, 0x45, 0xcb, 0x82,
0x12, 0xea, 0x28, 0x1a, 0xc9, 0xd0, 0xed, 0x0b, 0xb3, 0xd2, 0xf4, 0x6d, 0x9d, 0x87, 0xe5, 0x29,
0xb7, 0x6a, 0xfd, 0x4d, 0x45, 0x6b, 0x08, 0x72, 0x50, 0x48, 0x67, 0x38, 0x28, 0x5a, 0x3b, 0x93,
0x8d, 0x41, 0x29, 0xe3, 0x36, 0xe6, 0x5d, 0x28, 0xe3, 0xc4, 0x12, 0x13, 0x33, 0x07, 0xfb, 0x13,
0x24, 0x77, 0x34, 0x17, 0x6f, 0x42, 0xb5, 0xd3, 0x13, 0x9d, 0x03, 0xe1, 0x19, 0x5b, 0x9f, 0x80,
0xa8, 0x34, 0x9d, 0x4c, 0x94, 0xad, 0x01, 0x52, 0x89, 0x8e, 0x0c, 0x1f, 0xf4, 0xe5, 0x27, 0x3e,
0xed, 0x2b, 0xaa, 0x44, 0x82, 0x48, 0x5a, 0xb7, 0x51, 0x47, 0xcc, 0xb6, 0x8d, 0x10, 0xd6, 0x03,
0x28, 0x53, 0xdf, 0x78, 0x12, 0xf4, 0x98, 0x75, 0xaa, 0x78, 0x7d, 0xbe, 0x31, 0x9b, 0x21, 0x5b,
0x7f, 0x51, 0x80, 0x12, 0xc2, 0xfc, 0x26, 0x94, 0x23, 0x37, 0xec, 0xea, 0x0d, 0x98, 0xce, 0x38,
0x1d, 0x6c, 0x73, 0x34, 0x09, 0xbf, 0x6f, 0x54, 0xb1, 0x30, 0x87, 0xb2, 0xa4, 0x3d, 0x66, 0xd5,
0x72, 0x05, 0xca, 0x03, 0x37, 0x72, 0xfb, 0xe6, 0x9c, 0x68, 0xc0, 0xfe, 0x69, 0x1e, 0x4a, 0x48,
0xc4, 0x97, 0x61, 0xb1, 0xa5, 0x22, 0xff, 0x40, 0xa8, 0x5e, 0x24, 0x87, 0xdd, 0x9e, 0xd6, 0xa4,
0x47, 0xe2, 0x58, 0xdb, 0x1b, 0x6d, 0x10, 0x94, 0x1b, 0xf8, 0x1d, 0x56, 0x40, 0xad, 0x5a, 0x97,
0x81, 0xc7, 0x8a, 0xfc, 0x1c, 0x34, 0x9e, 0x85, 0x9e, 0x88, 0xe2, 0x8e, 0x8c, 0x84, 0xc7, 0x4a,
0xe6, 0x74, 0x1f, 0xb0, 0x32, 0xf9, 0x32, 0x71, 0xa4, 0x28, 0xa5, 0x61, 0x15, 0x7e, 0x1e, 0xce,
0xad, 0x8f, 0xe7, 0x39, 0xac, 0x8a, 0x36, 0xe9, 0x89, 0x08, 0x51, 0xc9, 0x58, 0x4d, 0x2b, 0xb1,
0xfc, 0xc4, 0x67, 0x75, 0xec, 0x4c, 0x9f, 0x13, 0x06, 0xf6, 0xdf, 0xe6, 0x13, 0xcb, 0xb1, 0x08,
0xf5, 0x5d, 0x37, 0x72, 0xbb, 0x91, 0x3b, 0xc0, 0xf1, 0x35, 0xa0, 0xaa, 0x1d, 0xe7, 0x9b, 0xda,
0xba, 0x69, 0xe0, 0xb6, 0xb6, 0x8d, 0x1a, 0xb8, 0xc3, 0x8a, 0x23, 0xe0, 0x2e, 0x2b, 0x61, 0x1f,
0x1f, 0x0e, 0xa5, 0x12, 0xac, 0x4c, 0xb6, 0x4e, 0x7a, 0x82, 0x55, 0x10, 0xb9, 0x87, 0x16, 0x85,
0x55, 0x71, 0xce, 0x1b, 0xa8, 0x3f, 0x6d, 0x79, 0xc4, 0x6a, 0x38, 0x0c, 0x5c, 0x46, 0xe1, 0xb1,
0x3a, 0xb6, 0x3c, 0x1d, 0xf6, 0xdb, 0x02, 0xa7, 0x09, 0xd8, 0xb2, 0x27, 0xbb, 0xdd, 0x40, 0xb0,
0x06, 0xae, 0x41, 0xc6, 0xf8, 0xb2, 0x05, 0xb2, 0xb4, 0x6e, 0x10, 0xc8, 0xa1, 0x62, 0x8b, 0xd6,
0x17, 0x45, 0x28, 0x61, 0x92, 0x82, 0x67, 0xa7, 0x87, 0x76, 0xc6, 0x9c, 0x1d, 0xfc, 0x4e, 0x4f,
0x60, 0x61, 0x74, 0x02, 0xf9, 0x3b, 0x66, 0xa7, 0x8b, 0x73, 0x58, 0x59, 0x14, 0x9c, 0xdd, 0x64,
0x0e, 0xa5, 0xbe, 0xdf, 0x17, 0xc6, 0xd6, 0xd1, 0x37, 0xe2, 0x62, 0xf4, 0xc7, 0x78, 0x0c, 0x8a,
0x0e, 0x7d, 0xe3, 0xa9, 0x71, 0xd1, 0x2d, 0xac, 0x29, 0x3a, 0x03, 0x45, 0x27, 0x01, 0xf5, 0x69,
0x46, 0xab, 0x54, 0x9d, 0xe3, 0x34, 0x53, 0xf7, 0x59, 0x8b, 0x34, 0x32, 0x06, 0xb5, 0xf9, 0xd9,
0x33, 0x4e, 0x62, 0xd3, 0x68, 0xe3, 0xc8, 0x81, 0xd5, 0xf4, 0xea, 0xb1, 0x3c, 0xee, 0x12, 0x1d,
0x43, 0x6d, 0xcb, 0x9e, 0xfb, 0x9e, 0x90, 0xac, 0x48, 0x0e, 0x6e, 0xe8, 0xf9, 0x92, 0x95, 0x30,
0xa2, 0xda, 0xdd, 0x7c, 0xc8, 0xca, 0xf6, 0xf5, 0x8c, 0xab, 0x59, 0x1b, 0x2a, 0xa9, 0xc5, 0x90,
0x5a, 0xe6, 0xb5, 0x96, 0xb5, 0x85, 0xc7, 0x0a, 0xf6, 0xf7, 0x67, 0x98, 0xcf, 0x45, 0xa8, 0x3f,
0x1b, 0x04, 0xd2, 0xf5, 0x4e, 0xb1, 0x9f, 0x0b, 0x00, 0xa3, 0xa4, 0xd7, 0xfa, 0xc7, 0x2b, 0x23,
0x37, 0x8d, 0x31, 0x66, 0x2c, 0x87, 0x51, 0x47, 0x90, 0x69, 0xa8, 0x3b, 0x06, 0xe2, 0xef, 0x43,
0x19, 0xdb, 0xe3, 0x66, 0x81, 0x2c, 0xc6, 0xcd, 0xb9, 0x52, 0xad, 0xd5, 0xe7, 0xbe, 0x78, 0xe9,
0x68, 0x46, 0x7e, 0x2f, 0x1b, 0x76, 0xbc, 0xa2, 0x08, 0x34, 0xa2, 0xe4, 0x57, 0x01, 0xdc, 0x8e,
0xf2, 0x0f, 0x05, 0xca, 0x32, 0x67, 0x3f, 0x83, 0xe1, 0x0e, 0x34, 0xf0, 0x48, 0x0e, 0x76, 0x22,
0x3c, 0xc5, 0xcd, 0x05, 0x12, 0xfc, 0xc6, 0x7c, 0xc3, 0xfb, 0x20, 0x65, 0x74, 0xb2, 0x42, 0xf8,
0x33, 0x58, 0xd0, 0x05, 0x26, 0x23, 0x74, 0x91, 0x84, 0xbe, 0x39, 0x9f, 0xd0, 0x9d, 0x11, 0xa7,
0x33, 0x26, 0x66, 0xba, 0x6e, 0x54, 0x3e, 0x6b, 0xdd, 0x08, 0x7d, 0xf3, 0xde, 0xb8, 0x6f, 0xd6,
0x2e, 0x60, 0x02, 0x6b, 0xfd, 0xac, 0x0c, 0x25, 0x5a, 0x9e, 0xc9, 0xf2, 0xd2, 0xc6, 0x98, 0x19,
0xbe, 0x35, 0xff, 0x36, 0x4e, 0x9c, 0x52, 0x3a, 0xf5, 0xc5, 0xcc, 0xa9, 0x7f, 0x1f, 0xca, 0xb1,
0x8c, 0x54, 0xb2, 0xb5, 0x73, 0x2a, 0x48, 0x4b, 0x46, 0xca, 0xd1, 0x8c, 0xfc, 0x21, 0x54, 0xf7,
0xfd, 0x40, 0xe1, 0x82, 0xeb, 0x85, 0x79, 0x7d, 0x3e, 0x19, 0x0f, 0x89, 0xc9, 0x49, 0x98, 0xf9,
0xe3, 0xac, 0xa2, 0x55, 0x48, 0xd2, 0xea, 0x7c, 0x92, 0x66, 0xe9, 0xdf, 0x4d, 0x60, 0x1d, 0x79,
0x28, 0xa2, 0xa4, 0xed, 0x91, 0x38, 0x36, 0x8e, 0x75, 0x0a, 0xcf, 0x2d, 0xa8, 0xf5, 0x7c, 0x4f,
0x60, 0x6c, 0x42, 0xf6, 0xa3, 0xe6, 0xa4, 0x30, 0x7f, 0x04, 0x35, 0x8a, 0xe9, 0xd1, 0x92, 0xd5,
0xcf, 0xbc, 0xf8, 0x3a, 0xbd, 0x48, 0x04, 0x60, 0x47, 0xd4, 0xf9, 0x43, 0x5f, 0x35, 0x41, 0x77,
0x94, 0xc0, 0x38, 0x60, 0xd2, 0xe5, 0xec, 0x80, 0x1b, 0x7a, 0xc0, 0x93, 0x78, 0x7e, 0x17, 0x2e,
0x10, 0x6e, 0xc2, 0xb1, 0xe1, 0x31, 0x42, 0xa1, 0xb3, 0x1b, 0x31, 0xc8, 0x18, 0xb8, 0x5d, 0xf1,
0xd8, 0xef, 0xfb, 0xaa, 0xb9, 0x78, 0x2d, 0x7f, 0xa3, 0xec, 0x8c, 0x10, 0xf6, 0x5d, 0x63, 0x02,
0xd1, 0x29, 0x61, 0xee, 0x97, 0x18, 0xaf, 0x58, 0x69, 0x2f, 0xf7, 0x81, 0x1b, 0x04, 0x22, 0x3a,
0xd6, 0x89, 0xe3, 0x23, 0x37, 0x6c, 0xbb, 0x21, 0x2b, 0xda, 0x37, 0xa0, 0x44, 0x33, 0xab, 0x43,
0x59, 0x27, 0x18, 0x94, 0x6c, 0x9a, 0xe4, 0x82, 0x8c, 0xde, 0x63, 0xd4, 0x70, 0x56, 0xb0, 0xfe,
0xba, 0x08, 0xb5, 0x64, 0x0e, 0x18, 0x6a, 0x1f, 0x88, 0xe3, 0x24, 0xd4, 0x3e, 0x10, 0xc7, 0x14,
0x01, 0xc5, 0xcf, 0xfd, 0xd8, 0x6f, 0x9b, 0x88, 0xae, 0xe6, 0x8c, 0x10, 0x18, 0x44, 0xbc, 0xf4,
0x3d, 0xd5, 0x23, 0xd5, 0x2d, 0x3b, 0x1a, 0xe0, 0x37, 0xe0, 0x9c, 0xe7, 0x2a, 0xb1, 0x1d, 0x76,
0x82, 0xa1, 0x27, 0xf6, 0xd0, 0x01, 0xe9, 0x0c, 0x7b, 0x12, 0xcd, 0x7f, 0x08, 0xa0, 0xfc, 0xbe,
0x78, 0x28, 0xa3, 0xbe, 0xab, 0x4c, 0x58, 0xfd, 0x83, 0xb3, 0x29, 0xd7, 0xea, 0x5e, 0x2a, 0xc0,
0xc9, 0x08, 0x43, 0xd1, 0xd8, 0x9b, 0x11, 0x5d, 0xfd, 0x5a, 0xa2, 0x37, 0x53, 0x01, 0x4e, 0x46,
0x98, 0xfd, 0x1b, 0x00, 0xa3, 0x16, 0x7e, 0x11, 0xf8, 0x13, 0x19, 0xaa, 0xde, 0x5a, 0xbb, 0x1d,
0xad, 0x8b, 0x7d, 0x19, 0x89, 0x4d, 0x17, 0x3d, 0xc7, 0x05, 0x58, 0x4e, 0xf1, 0x6b, 0xfb, 0x4a,
0x44, 0x88, 0xa6, 0xa5, 0x6f, 0xf5, 0x64, 0xa4, 0x74, 0x58, 0x42, 0x9f, 0xcf, 0x5a, 0xac, 0x88,
0xde, 0x6a, 0xbb, 0xb5, 0xc3, 0x4a, 0xf6, 0x0d, 0x80, 0xd1, 0x94, 0x28, 0x7c, 0xa7, 0xaf, 0x37,
0x6f, 0x9b, 0x60, 0x9e, 0xa0, 0xdb, 0x77, 0x59, 0xde, 0xfa, 0xf3, 0x02, 0x94, 0xf0, 0xc4, 0x63,
0xe6, 0x92, 0x55, 0x4f, 0xbd, 0x7d, 0x59, 0xd4, 0xd7, 0xb3, 0x53, 0x28, 0x3b, 0x6b, 0xa7, 0xde,
0x86, 0x46, 0x67, 0x18, 0x2b, 0xd9, 0x27, 0x03, 0xdc, 0x2c, 0x92, 0x2d, 0xb8, 0x38, 0x55, 0x03,
0x78, 0xee, 0x06, 0x43, 0xe1, 0x64, 0x49, 0xf9, 0x3d, 0xa8, 0xec, 0xeb, 0x8d, 0xd0, 0x55, 0x80,
0x6f, 0x9c, 0x60, 0xa3, 0xcd, 0x62, 0x1b, 0x62, 0x9c, 0x97, 0x3f, 0xa5, 0x44, 0x59, 0x94, 0xfd,
0x2d, 0x73, 0x3a, 0xaa, 0x50, 0x5c, 0x8b, 0x3b, 0x26, 0x87, 0x14, 0x71, 0x47, 0x07, 0xa8, 0x1b,
0x34, 0x04, 0x56, 0xb0, 0xfe, 0xbe, 0x0a, 0x15, 0x6d, 0xd7, 0x8c, 0x05, 0xaf, 0xa7, 0x16, 0xfc,
0x43, 0xa8, 0xc9, 0x81, 0x88, 0x5c, 0x25, 0x23, 0x93, 0xc8, 0xde, 0x3b, 0x8b, 0x9d, 0x5c, 0xdd,
0x31, 0xcc, 0x4e, 0x2a, 0x66, 0x72, 0x3b, 0x0a, 0xd3, 0xdb, 0x71, 0x13, 0x58, 0x62, 0x12, 0x77,
0x23, 0xe4, 0x53, 0xc7, 0x26, 0x2d, 0x99, 0xc2, 0xf3, 0x3d, 0xa8, 0x77, 0x64, 0xe8, 0xf9, 0x69,
0x52, 0xbb, 0x74, 0xfb, 0xfb, 0x67, 0x1a, 0xe1, 0x46, 0xc2, 0xed, 0x8c, 0x04, 0xf1, 0xd7, 0xa1,
0x7c, 0x88, 0xfb, 0x44, 0x1b, 0x72, 0xf2, 0x2e, 0x6a, 0x22, 0xfe, 0x11, 0x34, 0x3e, 0x1d, 0xfa,
0x9d, 0x83, 0x9d, 0x6c, 0xd1, 0xe4, 0xed, 0x33, 0x8d, 0xe2, 0xc3, 0x11, 0xbf, 0x93, 0x15, 0x96,
0xd1, 0x8d, 0xea, 0xcf, 0xa1, 0x1b, 0xb5, 0x69, 0xdd, 0xb8, 0x0c, 0xb5, 0x64, 0x73, 0x48, 0x3f,
0x42, 0x8f, 0xe5, 0x78, 0x05, 0x0a, 0x3b, 0x11, 0xcb, 0xdb, 0x5f, 0xe5, 0xa1, 0x9e, 0x2e, 0xcc,
0x78, 0x81, 0xe4, 0xc1, 0xa7, 0x43, 0x37, 0x60, 0x79, 0x8a, 0xf0, 0xa5, 0xd2, 0x10, 0x1d, 0xd6,
0x0f, 0x22, 0xe1, 0x2a, 0xaa, 0xcb, 0xa1, 0x05, 0x16, 0x71, 0xcc, 0x4a, 0x9c, 0xc3, 0x92, 0x41,
0xef, 0x44, 0x9a, 0xb4, 0x8c, 0x09, 0x00, 0xb6, 0x26, 0x88, 0x8a, 0x36, 0xd8, 0x07, 0x42, 0x27,
0x38, 0x4f, 0xa5, 0x22, 0xa0, 0x86, 0x63, 0xd9, 0x0e, 0x59, 0x1d, 0xfb, 0x7c, 0x2a, 0xd5, 0x76,
0xc8, 0x60, 0x14, 0x79, 0x36, 0x92, 0xee, 0x09, 0x5a, 0xa0, 0xb8, 0x36, 0x08, 0xb6, 0x43, 0xb6,
0x68, 0x1a, 0x34, 0xb4, 0x84, 0x12, 0x1f, 0x1c, 0xb9, 0x1d, 0x64, 0x3f, 0xc7, 0x97, 0x00, 0x90,
0xc7, 0xc0, 0xcc, 0xfe, 0xe7, 0x3c, 0x34, 0x32, 0x0b, 0x8f, 0xd1, 0x2c, 0x35, 0xa2, 0xf9, 0xd2,
0xc1, 0xed, 0x0f, 0x45, 0xac, 0x44, 0xe4, 0x25, 0xa6, 0x69, 0x4f, 0xe2, 0x67, 0x01, 0xfb, 0xd8,
0x93, 0x7d, 0x19, 0x45, 0xf2, 0x25, 0x2b, 0x22, 0xf4, 0xd8, 0x8d, 0xd5, 0x0b, 0x21, 0x0e, 0x58,
0x09, 0xa7, 0xb7, 0x31, 0x8c, 0x22, 0x11, 0x6a, 0x44, 0x99, 0x06, 0x24, 0x8e, 0x34, 0x54, 0x41,
0xa1, 0x48, 0x4c, 0xb6, 0x8f, 0x55, 0x39, 0x83, 0x05, 0x43, 0xad, 0x31, 0x35, 0x24, 0x40, 0x72,
0x0d, 0xd6, 0x31, 0x11, 0xd4, 0x89, 0xd4, 0xce, 0xfe, 0xa6, 0x7b, 0x1c, 0xaf, 0x75, 0x25, 0x83,
0x49, 0xe4, 0x53, 0xf9, 0x92, 0x35, 0xac, 0x21, 0xc0, 0x28, 0xc4, 0xc4, 0xd0, 0x1a, 0xf5, 0x2b,
0x2d, 0x75, 0x1a, 0x88, 0xef, 0x00, 0xe0, 0x17, 0x51, 0x26, 0xf1, 0xf5, 0x19, 0x62, 0x03, 0xe2,
0x73, 0x32, 0x22, 0xac, 0xdf, 0x86, 0x7a, 0xda, 0x80, 0x99, 0x12, 0x79, 0xf1, 0xb4, 0xdb, 0x04,
0x44, 0x5f, 0xe8, 0x87, 0x9e, 0x38, 0xa2, 0xf3, 0x5e, 0x76, 0x34, 0x80, 0xa3, 0xec, 0xf9, 0x9e,
0x27, 0xc2, 0xa4, 0x20, 0xad, 0xa1, 0x59, 0xb7, 0x7f, 0xa5, 0x99, 0xb7, 0x7f, 0xd6, 0x6f, 0x42,
0x23, 0x13, 0x03, 0x9f, 0x38, 0xed, 0xcc, 0xc0, 0x0a, 0xe3, 0x03, 0xbb, 0x02, 0x75, 0x69, 0x02,
0xd9, 0x98, 0x8c, 0x76, 0xdd, 0x19, 0x21, 0xac, 0xbf, 0x2a, 0x40, 0x59, 0x4f, 0x6d, 0x32, 0xb6,
0x7d, 0x08, 0x15, 0x4c, 0xe2, 0x86, 0xc9, 0xd5, 0xe9, 0x9c, 0xf1, 0x63, 0x8b, 0x78, 0xb6, 0x72,
0x8e, 0xe1, 0xe6, 0xef, 0x42, 0x51, 0xb9, 0x5d, 0x53, 0xcf, 0xf9, 0xce, 0x7c, 0x42, 0xf6, 0xdc,
0xee, 0x56, 0xce, 0x41, 0x3e, 0xfe, 0x18, 0x6a, 0x1d, 0x93, 0x82, 0x1b, 0x63, 0x35, 0x67, 0xf8,
0x99, 0x24, 0xee, 0x5b, 0x39, 0x27, 0x95, 0xc0, 0xdf, 0x87, 0x12, 0x7a, 0x72, 0xb2, 0xb6, 0x73,
0x87, 0xd5, 0x78, 0x5c, 0xb6, 0x72, 0x0e, 0x71, 0xae, 0x57, 0xa1, 0x4c, 0xb6, 0xd1, 0x6a, 0x42,
0x45, 0xcf, 0x75, 0x72, 0xe5, 0xac, 0x4b, 0x50, 0xdc, 0x73, 0xbb, 0x18, 0x4d, 0xf9, 0x5e, 0x6c,
0x32, 0x3f, 0xfc, 0xb4, 0x5e, 0x1b, 0x95, 0x13, 0xb2, 0x95, 0xaa, 0xfc, 0x58, 0xa5, 0xca, 0xaa,
0x40, 0x09, 0x7b, 0xb4, 0xae, 0x9c, 0x16, 0x99, 0x59, 0x97, 0x31, 0x86, 0x53, 0xe2, 0x68, 0x56,
0x11, 0xce, 0x5a, 0x86, 0x73, 0x13, 0x77, 0x4e, 0x56, 0xd5, 0x04, 0x90, 0xd6, 0x22, 0x34, 0x32,
0xb7, 0x08, 0xd6, 0x75, 0xa8, 0x25, 0x77, 0x0c, 0x18, 0x08, 0xfb, 0xb1, 0xae, 0x8e, 0x98, 0x41,
0xa5, 0xb0, 0xf5, 0x09, 0x54, 0xf4, 0x35, 0x0d, 0x5f, 0x4f, 0xaf, 0x55, 0xf3, 0x73, 0xd4, 0xf4,
0x35, 0x93, 0xb9, 0x11, 0x49, 0xee, 0x56, 0xed, 0x2b, 0xe9, 0xbd, 0x4a, 0x92, 0x8a, 0x93, 0xef,
0xde, 0x8b, 0x84, 0x60, 0x79, 0x7b, 0x1f, 0x6a, 0xbb, 0x32, 0x9e, 0xb4, 0xcd, 0x55, 0x28, 0xee,
0xc9, 0x81, 0x76, 0xed, 0xeb, 0x52, 0x91, 0x6b, 0xd7, 0xa6, 0x78, 0x5f, 0xe9, 0xd4, 0xdf, 0xf1,
0xbb, 0x3d, 0xa5, 0xcb, 0x3a, 0xdb, 0x61, 0x28, 0x22, 0x56, 0x46, 0xfb, 0xe8, 0x88, 0x41, 0xe0,
0x76, 0x04, 0xab, 0xa0, 0x7d, 0x24, 0xfc, 0x43, 0x3f, 0x8a, 0x15, 0xab, 0xda, 0x6f, 0xa1, 0x55,
0xf5, 0xbb, 0x64, 0x18, 0xe9, 0x83, 0x44, 0xe5, 0xd0, 0xc4, 0x11, 0xb8, 0x21, 0x42, 0x34, 0xf8,
0x54, 0x9d, 0xd7, 0xd7, 0xe3, 0xd4, 0x41, 0xc1, 0x7e, 0x01, 0x8b, 0x63, 0xd7, 0xe6, 0x7c, 0x05,
0xd8, 0x18, 0x02, 0x07, 0x9a, 0xe3, 0x97, 0xe0, 0xfc, 0x18, 0xf6, 0x89, 0xef, 0x79, 0x54, 0xbc,
0x98, 0x6c, 0x48, 0xa6, 0xb3, 0x5e, 0x87, 0x6a, 0x47, 0x2f, 0x9c, 0xbd, 0x0b, 0x8b, 0xb4, 0x92,
0x4f, 0x84, 0x72, 0x77, 0xc2, 0xe0, 0xf8, 0xe7, 0x7e, 0xdb, 0x60, 0x7f, 0x17, 0xca, 0x54, 0x44,
0x44, 0x95, 0xd9, 0x8f, 0x64, 0x9f, 0x64, 0x95, 0x1d, 0xfa, 0x46, 0xe9, 0x4a, 0x1a, 0xe3, 0x55,
0x50, 0xd2, 0xfe, 0x17, 0x80, 0xea, 0x5a, 0xa7, 0x23, 0x87, 0xa1, 0x9a, 0xea, 0x79, 0x56, 0x9d,
0xea, 0x1e, 0x54, 0xdc, 0x43, 0x57, 0xb9, 0x91, 0x39, 0xe9, 0x93, 0x7e, 0xdc, 0xc8, 0x5a, 0x5d,
0x23, 0x22, 0xc7, 0x10, 0x23, 0x5b, 0x47, 0x86, 0xfb, 0x7e, 0xd7, 0x1c, 0xee, 0x93, 0xd8, 0x36,
0x88, 0xc8, 0x31, 0xc4, 0xc8, 0x66, 0x8c, 0x53, 0xf9, 0x54, 0x36, 0x7d, 0x42, 0x53, 0x5b, 0x74,
0x0b, 0x4a, 0x7e, 0xb8, 0x2f, 0xcd, 0xab, 0x96, 0xcb, 0x27, 0x30, 0x6d, 0x87, 0xfb, 0xd2, 0x21,
0x42, 0x4b, 0x40, 0x45, 0x0f, 0x98, 0xff, 0x00, 0xca, 0x74, 0x57, 0x60, 0xaa, 0xb3, 0x73, 0x3d,
0x43, 0xd0, 0x1c, 0xfc, 0x62, 0x52, 0x7a, 0xa6, 0xf5, 0x42, 0x3c, 0x81, 0xeb, 0xb5, 0x64, 0xc9,
0xac, 0xff, 0xcc, 0x43, 0x45, 0xcf, 0x90, 0x5f, 0x87, 0x25, 0x11, 0xe2, 0x81, 0x4c, 0xcc, 0x8f,
0x39, 0x89, 0x13, 0x58, 0x0c, 0x80, 0x0c, 0x46, 0xb4, 0x87, 0x5d, 0x93, 0x9b, 0x65, 0x51, 0xfc,
0x6d, 0xb8, 0xa4, 0xc1, 0xdd, 0x48, 0x44, 0x22, 0x10, 0x6e, 0x2c, 0x36, 0x7a, 0x6e, 0x18, 0x8a,
0xc0, 0x38, 0xa3, 0x93, 0x9a, 0xb9, 0x0d, 0x0b, 0xba, 0xa9, 0x35, 0x70, 0x3b, 0x22, 0x36, 0xa5,
0xf4, 0x31, 0x1c, 0xff, 0x1e, 0x94, 0xe9, 0x6d, 0x51, 0xd3, 0x3b, 0x5d, 0xf9, 0x34, 0x95, 0x25,
0x53, 0x6b, 0xb9, 0x06, 0xa0, 0x77, 0x03, 0x23, 0x77, 0x63, 0x42, 0xbe, 0x79, 0xea, 0xf6, 0x51,
0x0e, 0x92, 0x61, 0xc2, 0xf1, 0x79, 0x22, 0x10, 0x68, 0x1f, 0xd0, 0x52, 0xd2, 0xe4, 0x8b, 0xce,
0x18, 0xce, 0xfa, 0xbb, 0x12, 0x94, 0x70, 0x23, 0x91, 0xb8, 0x27, 0xfb, 0x22, 0x2d, 0xf1, 0x68,
0xa5, 0x1d, 0xc3, 0xa1, 0x3b, 0x76, 0xf5, 0xed, 0x59, 0x4a, 0xa6, 0xab, 0x31, 0x93, 0x68, 0xa4,
0x1c, 0x44, 0x72, 0xdf, 0x0f, 0x46, 0x94, 0xc6, 0x71, 0x4f, 0xa0, 0x71, 0xf9, 0xfb, 0x6e, 0x74,
0x20, 0x14, 0x59, 0x1f, 0x1c, 0x77, 0xca, 0xa1, 0x63, 0xfd, 0x93, 0x9a, 0xf9, 0xfb, 0x70, 0x39,
0xd3, 0x94, 0xf8, 0x80, 0x89, 0x1a, 0xd5, 0x69, 0x24, 0x13, 0x12, 0xf6, 0x44, 0x7f, 0x10, 0xb8,
0x4a, 0x4c, 0xdc, 0x40, 0x9d, 0x46, 0xc2, 0xbf, 0x0f, 0x17, 0x33, 0xcd, 0x2f, 0x64, 0x74, 0x10,
0xe3, 0xbe, 0x6f, 0x7b, 0xa6, 0xfa, 0x71, 0x42, 0x2b, 0xba, 0x10, 0x4f, 0x1c, 0xfa, 0x44, 0x59,
0x23, 0xca, 0x14, 0x46, 0xd5, 0x76, 0xf5, 0xc6, 0xb6, 0x8c, 0x2c, 0x9d, 0x87, 0x4d, 0x60, 0x31,
0x62, 0xd1, 0xef, 0x00, 0xe2, 0x6d, 0x8f, 0x0a, 0x32, 0x75, 0x67, 0x84, 0xe0, 0x57, 0x01, 0xba,
0xae, 0x12, 0x2f, 0xdd, 0xe3, 0x67, 0x51, 0xd0, 0x14, 0xba, 0x84, 0x39, 0xc2, 0x60, 0x72, 0x15,
0xc8, 0x8e, 0x1b, 0xb4, 0x94, 0x8c, 0xdc, 0xae, 0xd8, 0x75, 0x55, 0xaf, 0xd9, 0xd5, 0xc9, 0xd5,
0x24, 0x1e, 0x47, 0xab, 0xfc, 0xbe, 0xf8, 0x48, 0x86, 0xa2, 0xd9, 0xd3, 0xa3, 0x4d, 0x60, 0x7b,
0x07, 0x60, 0xa4, 0x7e, 0xe8, 0x73, 0xd6, 0xa8, 0x4c, 0xca, 0x72, 0x18, 0x9d, 0xee, 0x8a, 0xd0,
0xf3, 0xc3, 0xee, 0xa6, 0xd1, 0x38, 0x96, 0x47, 0x64, 0x4b, 0xb9, 0x91, 0x12, 0x5e, 0x8a, 0xa4,
0xac, 0x81, 0x20, 0xe1, 0xb1, 0xa2, 0xfd, 0xbf, 0x79, 0x68, 0x64, 0x2e, 0x09, 0x7f, 0x81, 0x17,
0x9b, 0xe8, 0xb7, 0xd1, 0xd2, 0xe0, 0x82, 0x68, 0x6d, 0x4c, 0x61, 0x5c, 0x2e, 0x73, 0x87, 0x89,
0xad, 0x5a, 0xf3, 0x32, 0x98, 0xaf, 0x75, 0xa9, 0x69, 0xdf, 0x36, 0x79, 0x77, 0x03, 0xaa, 0xcf,
0xc2, 0x83, 0x50, 0xbe, 0x0c, 0xb5, 0xff, 0xa6, 0x9b, 0xea, 0xb1, 0xda, 0x7c, 0x72, 0x99, 0x5c,
0xb4, 0x7f, 0x52, 0x9a, 0x78, 0xd4, 0xf1, 0x00, 0x2a, 0x3a, 0x0e, 0xa5, 0x10, 0x69, 0xfa, 0x16,
0x3e, 0x4b, 0x6c, 0xea, 0xc0, 0x19, 0x94, 0x63, 0x98, 0x31, 0x40, 0x4c, 0x5f, 0x2e, 0x15, 0x66,
0xd6, 0xab, 0xc7, 0x04, 0x25, 0x06, 0x74, 0xec, 0xf1, 0x5e, 0x2a, 0xc1, 0xfa, 0x71, 0x1e, 0x56,
0x66, 0x91, 0x60, 0xbc, 0xd6, 0x1e, 0x7b, 0x5b, 0x91, 0x80, 0xbc, 0x35, 0xf1, 0x64, 0xb0, 0x40,
0xb3, 0xb9, 0x75, 0xc6, 0x41, 0x8c, 0x3f, 0x20, 0xb4, 0x3f, 0xcf, 0xc3, 0xf2, 0xd4, 0x9c, 0x33,
0xc1, 0x10, 0x40, 0x45, 0x6b, 0x96, 0x7e, 0x0a, 0x90, 0x5e, 0xce, 0xea, 0x42, 0x20, 0x79, 0xa3,
0x58, 0xdf, 0x76, 0x6d, 0xea, 0x07, 0xa7, 0xac, 0x84, 0x51, 0x0c, 0xee, 0x1a, 0x5a, 0xf9, 0xae,
0x60, 0x65, 0xcc, 0xcd, 0x74, 0x10, 0x66, 0x30, 0x15, 0xca, 0xfb, 0x8c, 0x25, 0x60, 0x55, 0x7a,
0x62, 0x30, 0x1c, 0x04, 0x7e, 0x07, 0xc1, 0x9a, 0xed, 0xc0, 0xf9, 0x19, 0xe3, 0xa6, 0x91, 0x3c,
0x37, 0xa3, 0x5a, 0x02, 0xd8, 0x7c, 0x9e, 0x8c, 0x85, 0xe5, 0x31, 0x3d, 0xde, 0x7c, 0xbe, 0x41,
0x09, 0xb2, 0xb9, 0xc0, 0xd3, 0x67, 0xe2, 0x39, 0x66, 0x54, 0x31, 0x2b, 0xda, 0xf7, 0xe1, 0xc2,
0x5e, 0x2f, 0x12, 0xae, 0xb7, 0x29, 0xc4, 0x20, 0x40, 0x65, 0x73, 0x8f, 0x03, 0xe9, 0x7a, 0x33,
0x4a, 0x91, 0x2b, 0x50, 0x76, 0x3d, 0x2f, 0xd2, 0xeb, 0x5b, 0x77, 0x34, 0x60, 0x7f, 0x0c, 0x17,
0xb5, 0x00, 0xdd, 0xcb, 0x87, 0x43, 0x31, 0x14, 0x0f, 0x42, 0x15, 0x1d, 0xeb, 0x52, 0x73, 0xf2,
0xd2, 0x54, 0xd3, 0x18, 0x71, 0x53, 0x78, 0xb2, 0x03, 0xf4, 0x95, 0xfa, 0x87, 0x14, 0xb6, 0xff,
0xaf, 0x04, 0xb0, 0x93, 0x3e, 0x90, 0x9d, 0x71, 0x6a, 0x67, 0x45, 0x43, 0x53, 0x97, 0x13, 0xc5,
0x33, 0x5f, 0x4e, 0xbc, 0x9d, 0x86, 0xd9, 0xba, 0x68, 0x36, 0xf9, 0x02, 0x71, 0x34, 0xa6, 0x89,
0xe0, 0x7a, 0xfc, 0x52, 0xbb, 0x3c, 0x79, 0xa9, 0x7d, 0x6d, 0xfa, 0x05, 0xcc, 0x84, 0x39, 0x19,
0x25, 0xad, 0xd5, 0xb1, 0xa4, 0xd5, 0x82, 0x1a, 0xae, 0x89, 0x0c, 0x83, 0xe3, 0xa4, 0x4e, 0x9e,
0xc0, 0xfc, 0x0e, 0x94, 0x15, 0x3d, 0x29, 0xae, 0x91, 0xf6, 0x4f, 0xc6, 0x63, 0xa3, 0x57, 0xd6,
0x64, 0x45, 0x34, 0x2d, 0xda, 0x26, 0x3f, 0x36, 0xcf, 0x56, 0xb4, 0x33, 0xa8, 0x39, 0x19, 0x0c,
0x5f, 0x05, 0xee, 0x87, 0xb1, 0x72, 0x83, 0x40, 0x78, 0xeb, 0xc7, 0x9b, 0x62, 0xdf, 0x1d, 0x06,
0x8a, 0x1c, 0x50, 0xcd, 0x99, 0xd1, 0x62, 0xff, 0xdb, 0xe8, 0xb9, 0x56, 0x1d, 0xca, 0x6d, 0x37,
0xf6, 0x3b, 0xfa, 0x62, 0xd8, 0xf8, 0x66, 0x7d, 0x83, 0xa7, 0xa4, 0x27, 0x59, 0x01, 0xd3, 0x89,
0x58, 0x60, 0xe2, 0xb0, 0x04, 0x30, 0x7a, 0x00, 0xcd, 0x4a, 0x78, 0x08, 0x92, 0x9d, 0xd0, 0xf7,
0xc2, 0xc4, 0x4a, 0x95, 0x0d, 0x2f, 0x7d, 0x71, 0x53, 0xc5, 0x1e, 0xc8, 0xc8, 0xb2, 0x1a, 0xd2,
0x84, 0x52, 0x09, 0x5d, 0xcb, 0x21, 0x4f, 0xc8, 0x00, 0xc5, 0x24, 0xef, 0x39, 0x59, 0x03, 0x23,
0xfe, 0x44, 0xa8, 0x2e, 0xc6, 0xc4, 0x54, 0xc3, 0x5f, 0xc0, 0x23, 0x32, 0xde, 0xa0, 0x4b, 0x3c,
0x68, 0x90, 0xda, 0x6e, 0x2c, 0xd8, 0x8a, 0xfd, 0xc7, 0xa3, 0x59, 0xbd, 0x91, 0x06, 0xe2, 0xf3,
0xe8, 0xc3, 0x49, 0xa1, 0xfa, 0x03, 0x58, 0x8e, 0xc4, 0xa7, 0x43, 0x7f, 0xec, 0x85, 0x65, 0xf1,
0xf4, 0x3b, 0xc4, 0x69, 0x0e, 0xfb, 0x10, 0x96, 0x13, 0xe0, 0x85, 0xaf, 0x7a, 0x94, 0x15, 0xf3,
0x3b, 0x99, 0x27, 0xa0, 0x79, 0x13, 0x19, 0x9e, 0x20, 0x72, 0xf4, 0xe4, 0x33, 0xad, 0x46, 0x16,
0xe6, 0xa8, 0x46, 0xda, 0xff, 0x51, 0xc9, 0x24, 0xc6, 0x3a, 0x35, 0xf1, 0xd2, 0xd4, 0x64, 0xda,
0x6e, 0x8c, 0x0a, 0x8c, 0x85, 0xb3, 0x14, 0x18, 0x67, 0xdd, 0xca, 0xbd, 0x83, 0x71, 0x27, 0xa9,
0xda, 0xf3, 0x39, 0x8a, 0xa7, 0x63, 0xb4, 0x7c, 0x9d, 0x2e, 0x24, 0xdc, 0x96, 0xbe, 0x0e, 0x2e,
0xcf, 0x7c, 0x90, 0x9d, 0xbd, 0x79, 0x30, 0x94, 0x4e, 0x86, 0x2b, 0x73, 0x30, 0x2b, 0xb3, 0x0e,
0x26, 0x66, 0x89, 0xe6, 0xc8, 0xa6, 0xb0, 0xae, 0x35, 0xeb, 0xef, 0x44, 0x3c, 0xbd, 0xa4, 0xae,
0x39, 0x53, 0x78, 0x34, 0xb1, 0xfd, 0x61, 0xa0, 0x7c, 0x53, 0x4e, 0xd5, 0xc0, 0xe4, 0x7f, 0x06,
0xea, 0xd3, 0xff, 0x19, 0x78, 0x0f, 0x20, 0x16, 0x68, 0x51, 0x37, 0xfd, 0x8e, 0x32, 0x97, 0xc6,
0x57, 0x4f, 0x9a, 0x9b, 0x29, 0x02, 0x67, 0x38, 0x70, 0xfc, 0x7d, 0xf7, 0x68, 0x03, 0x63, 0x40,
0x73, 0x03, 0x96, 0xc2, 0x93, 0xe6, 0x6a, 0x69, 0xda, 0x5c, 0xdd, 0x81, 0x72, 0xdc, 0x91, 0x03,
0x41, 0x8f, 0x9e, 0x4f, 0xde, 0xdf, 0xd5, 0x16, 0x12, 0x39, 0x9a, 0x96, 0xca, 0x2f, 0xe8, 0x31,
0x64, 0x44, 0xcf, 0x9d, 0xeb, 0x4e, 0x02, 0x5a, 0x1e, 0x54, 0x4c, 0xb9, 0x74, 0x46, 0xda, 0x4b,
0x95, 0x96, 0x42, 0xe6, 0xb9, 0x53, 0xfa, 0xac, 0xa8, 0x98, 0x7d, 0x56, 0x74, 0x0d, 0x1a, 0x51,
0xe6, 0x0a, 0xc0, 0xbc, 0x25, 0xcb, 0xa0, 0xec, 0x8f, 0xa0, 0x4c, 0xe3, 0x41, 0xf7, 0xa9, 0x97,
0x52, 0x47, 0x50, 0x38, 0x70, 0x96, 0xe7, 0x2b, 0xc0, 0x62, 0xa1, 0x76, 0xf6, 0xf7, 0x7a, 0xa2,
0xe5, 0xf6, 0x29, 0x3d, 0x60, 0x05, 0xde, 0x84, 0x15, 0x4d, 0x1b, 0x8f, 0xb7, 0x90, 0x9f, 0x0f,
0xfc, 0x76, 0xe4, 0x46, 0xc7, 0xac, 0x64, 0xbf, 0x47, 0x17, 0x54, 0x89, 0xd2, 0x34, 0xd2, 0xff,
0xa6, 0x68, 0x5b, 0xe8, 0x89, 0x08, 0x8d, 0xab, 0xbe, 0x3e, 0x34, 0x91, 0xb7, 0x7e, 0xd0, 0x40,
0xe1, 0x31, 0x2b, 0xda, 0x2f, 0x30, 0x50, 0x1b, 0xb9, 0xa2, 0x5f, 0xd8, 0x99, 0xb2, 0xd7, 0x33,
0x81, 0xca, 0xf8, 0x0b, 0x86, 0xfc, 0xbc, 0x2f, 0x18, 0xec, 0x47, 0x70, 0xce, 0x19, 0x37, 0xa4,
0xfc, 0x6d, 0xa8, 0xca, 0x41, 0x56, 0xce, 0xab, 0x74, 0x2f, 0x21, 0xb7, 0xff, 0x24, 0x0f, 0x0b,
0xdb, 0xa1, 0x12, 0x51, 0xe8, 0x06, 0x0f, 0x03, 0xb7, 0xcb, 0xdf, 0x4a, 0x2c, 0xd1, 0xec, 0xbc,
0x34, 0x4b, 0x3b, 0x6e, 0x94, 0x9e, 0x9a, 0xb2, 0x20, 0xbf, 0x00, 0xcb, 0xc2, 0xf3, 0x95, 0x8c,
0x74, 0x78, 0x96, 0x3c, 0x24, 0x59, 0x01, 0xa6, 0xd1, 0x2d, 0x52, 0xfb, 0x3d, 0xbd, 0xcd, 0x4d,
0x58, 0x19, 0xc3, 0x26, 0xb1, 0x57, 0xc1, 0xfe, 0xf7, 0x72, 0x12, 0x75, 0x3c, 0x37, 0x0f, 0x49,
0x22, 0x29, 0xd5, 0xa8, 0xec, 0xab, 0xa1, 0xcc, 0xdf, 0x94, 0x0a, 0x73, 0xfc, 0x4d, 0xe9, 0xbd,
0xd1, 0xdf, 0x94, 0xb4, 0xb9, 0x7f, 0x6d, 0xa6, 0x0f, 0xa1, 0x3b, 0x72, 0x13, 0x36, 0xb6, 0x44,
0xe6, 0x3f, 0x4b, 0x6f, 0x9a, 0x5c, 0x61, 0xf6, 0x2d, 0xde, 0x84, 0x8f, 0xd7, 0x97, 0x86, 0xf7,
0x26, 0x9f, 0xc7, 0xce, 0xf7, 0x4e, 0x65, 0x2a, 0x7e, 0x82, 0x33, 0xc7, 0x4f, 0xf7, 0x27, 0xc2,
0xf2, 0xda, 0xcc, 0x9a, 0xcf, 0x29, 0xff, 0xe1, 0xb9, 0x0f, 0xd5, 0x9e, 0x1f, 0x2b, 0x19, 0x1d,
0x53, 0x68, 0x32, 0xfd, 0x0e, 0x3e, 0xb3, 0x5a, 0x5b, 0x9a, 0x90, 0x1e, 0x16, 0x24, 0x5c, 0x56,
0x17, 0x60, 0xb4, 0x8a, 0x53, 0xd6, 0xe4, 0x6b, 0xfc, 0x67, 0xec, 0x22, 0x54, 0xe2, 0x61, 0x7b,
0x54, 0xc7, 0x37, 0x90, 0x75, 0x04, 0xd6, 0x94, 0x27, 0xde, 0x15, 0x91, 0x1e, 0x1f, 0x5a, 0xd7,
0xa4, 0xde, 0x6f, 0xba, 0x4f, 0x61, 0xfe, 0x5e, 0x76, 0x7b, 0xb4, 0x0a, 0x5d, 0x3b, 0x61, 0x8d,
0x53, 0xc9, 0x99, 0x7d, 0xb2, 0xee, 0x41, 0x23, 0x33, 0x75, 0xb4, 0x90, 0xc3, 0xd0, 0x93, 0x49,
0x61, 0x11, 0xbf, 0xf5, 0xdb, 0x7d, 0x2f, 0x29, 0x2d, 0xd2, 0xf7, 0xcd, 0x3f, 0x2a, 0xc2, 0xd2,
0xb8, 0xba, 0x50, 0x89, 0x55, 0x1b, 0xa3, 0x9d, 0xc0, 0xd3, 0x35, 0xd8, 0x75, 0x74, 0x50, 0x9d,
0x68, 0xd8, 0x6f, 0xc7, 0x3a, 0x72, 0xa3, 0xf4, 0x92, 0x61, 0xd3, 0xae, 0x0e, 0xe8, 0x08, 0xb1,
0x8c, 0x4d, 0x5b, 0xb2, 0x2f, 0xd8, 0xb5, 0xec, 0x33, 0xe8, 0x37, 0x92, 0x07, 0xd3, 0x14, 0x46,
0xbd, 0x8f, 0xf1, 0x5e, 0x4b, 0x28, 0xb6, 0x86, 0x69, 0x4f, 0x6b, 0x6f, 0x14, 0x2d, 0xb1, 0x8f,
0xd1, 0x06, 0xeb, 0x32, 0x35, 0x1b, 0xf0, 0xba, 0x79, 0x61, 0xf6, 0x59, 0x81, 0x2f, 0x66, 0xb2,
0xa1, 0x9f, 0x16, 0xf8, 0x0a, 0x9c, 0x5b, 0x1f, 0x86, 0x5e, 0x20, 0xbc, 0x14, 0xfb, 0x67, 0x84,
0x7d, 0x32, 0x5e, 0xc7, 0x61, 0x9f, 0xa3, 0xa5, 0x3e, 0xff, 0x64, 0xba, 0x3e, 0xc3, 0xfe, 0x70,
0xb2, 0x25, 0x95, 0xf4, 0x93, 0xac, 0xfc, 0x94, 0xfe, 0x33, 0x4c, 0xda, 0xea, 0xad, 0x61, 0xdb,
0x64, 0x4f, 0xbf, 0x53, 0xe2, 0x17, 0x61, 0xd9, 0x50, 0x65, 0xa6, 0xf0, 0xbb, 0x25, 0x7e, 0x1e,
0x96, 0xd6, 0xf4, 0xbe, 0x99, 0xb5, 0x61, 0xbf, 0x57, 0xc2, 0xc9, 0xd0, 0x5d, 0xdf, 0xef, 0x97,
0xf8, 0x32, 0x2c, 0xa4, 0x75, 0x1a, 0x5c, 0xe1, 0x1f, 0x93, 0xe8, 0x14, 0xc5, 0xfe, 0xa0, 0x74,
0xf3, 0x2f, 0xf3, 0xb0, 0x34, 0x6e, 0xb9, 0x71, 0x09, 0x03, 0x19, 0x76, 0x95, 0x7e, 0x0f, 0xbe,
0x08, 0xf5, 0xb8, 0x27, 0x23, 0x45, 0x20, 0xd5, 0xe1, 0x43, 0xba, 0xa5, 0xd3, 0x49, 0xa7, 0x2e,
0xd0, 0xe9, 0xb7, 0x0c, 0xca, 0xed, 0xb2, 0x06, 0xee, 0x8b, 0x87, 0xdd, 0x97, 0xd2, 0x28, 0x9a,
0x6e, 0x0b, 0x93, 0xdb, 0x18, 0x56, 0x41, 0xd2, 0x61, 0x14, 0xe8, 0x68, 0x5a, 0xf4, 0x5d, 0x3f,
0xd0, 0x0f, 0x3f, 0x07, 0x3d, 0xcc, 0x27, 0xeb, 0x1a, 0x2b, 0x3f, 0xf1, 0xf5, 0x13, 0x4b, 0xe3,
0x27, 0x3d, 0x1c, 0x47, 0xaa, 0x82, 0x4c, 0xac, 0xdf, 0xfc, 0xa7, 0x2f, 0xaf, 0xe6, 0xbf, 0xf8,
0xf2, 0x6a, 0xfe, 0xbf, 0xbe, 0xbc, 0x9a, 0xff, 0xfc, 0xab, 0xab, 0xb9, 0x2f, 0xbe, 0xba, 0x9a,
0xfb, 0xd9, 0x57, 0x57, 0x73, 0x1f, 0xb1, 0xc9, 0xff, 0x8c, 0xb6, 0x2b, 0x74, 0xb8, 0xee, 0xfc,
0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x19, 0xdf, 0xc6, 0x4e, 0x3a, 0x00, 0x00,
}
func (m *SmartBlockSnapshotBase) Marshal() (dAtA []byte, err error) {
@ -7236,6 +7278,13 @@ func (m *BlockContentDataview) MarshalToSizedBuffer(dAtA []byte) (int, error) {
dAtA[i] = 0x62
}
}
if len(m.TargetObjectId) > 0 {
i -= len(m.TargetObjectId)
copy(dAtA[i:], m.TargetObjectId)
i = encodeVarintModels(dAtA, i, uint64(len(m.TargetObjectId)))
i--
dAtA[i] = 0x32
}
if len(m.RelationLinks) > 0 {
for iNdEx := len(m.RelationLinks) - 1; iNdEx >= 0; iNdEx-- {
{
@ -7317,6 +7366,11 @@ func (m *BlockContentDataviewView) MarshalToSizedBuffer(dAtA []byte) (int, error
_ = i
var l int
_ = l
if m.PageLimit != 0 {
i = encodeVarintModels(dAtA, i, uint64(m.PageLimit))
i--
dAtA[i] = 0x68
}
if m.GroupBackgroundColors {
i--
if m.GroupBackgroundColors {
@ -7515,6 +7569,21 @@ func (m *BlockContentDataviewSort) MarshalToSizedBuffer(dAtA []byte) (int, error
_ = i
var l int
_ = l
if m.IncludeTime {
i--
if m.IncludeTime {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x28
}
if m.Format != 0 {
i = encodeVarintModels(dAtA, i, uint64(m.Format))
i--
dAtA[i] = 0x20
}
if len(m.CustomOrder) > 0 {
for iNdEx := len(m.CustomOrder) - 1; iNdEx >= 0; iNdEx-- {
{
@ -7564,6 +7633,13 @@ func (m *BlockContentDataviewFilter) MarshalToSizedBuffer(dAtA []byte) (int, err
_ = i
var l int
_ = l
if len(m.Id) > 0 {
i -= len(m.Id)
copy(dAtA[i:], m.Id)
i = encodeVarintModels(dAtA, i, uint64(len(m.Id)))
i--
dAtA[i] = 0x4a
}
if m.IncludeTime {
i--
if m.IncludeTime {
@ -10317,6 +10393,10 @@ func (m *BlockContentDataview) Size() (n int) {
n += 1 + l + sovModels(uint64(l))
}
}
l = len(m.TargetObjectId)
if l > 0 {
n += 1 + l + sovModels(uint64(l))
}
if len(m.GroupOrders) > 0 {
for _, e := range m.GroupOrders {
l = e.Size()
@ -10387,6 +10467,9 @@ func (m *BlockContentDataviewView) Size() (n int) {
if m.GroupBackgroundColors {
n += 2
}
if m.PageLimit != 0 {
n += 1 + sovModels(uint64(m.PageLimit))
}
return n
}
@ -10437,6 +10520,12 @@ func (m *BlockContentDataviewSort) Size() (n int) {
n += 1 + l + sovModels(uint64(l))
}
}
if m.Format != 0 {
n += 1 + sovModels(uint64(m.Format))
}
if m.IncludeTime {
n += 2
}
return n
}
@ -10473,6 +10562,10 @@ func (m *BlockContentDataviewFilter) Size() (n int) {
if m.IncludeTime {
n += 2
}
l = len(m.Id)
if l > 0 {
n += 1 + l + sovModels(uint64(l))
}
return n
}
@ -14507,6 +14600,38 @@ func (m *BlockContentDataview) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TargetObjectId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModels
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthModels
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthModels
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.TargetObjectId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 12:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field GroupOrders", wireType)
@ -14953,6 +15078,25 @@ func (m *BlockContentDataviewView) Unmarshal(dAtA []byte) error {
}
}
m.GroupBackgroundColors = bool(v != 0)
case 13:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field PageLimit", wireType)
}
m.PageLimit = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModels
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.PageLimit |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipModels(dAtA[iNdEx:])
@ -15267,6 +15411,45 @@ func (m *BlockContentDataviewSort) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType)
}
m.Format = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModels
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Format |= RelationFormat(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field IncludeTime", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModels
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.IncludeTime = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipModels(dAtA[iNdEx:])
@ -15513,6 +15696,38 @@ func (m *BlockContentDataviewFilter) Unmarshal(dAtA []byte) error {
}
}
m.IncludeTime = bool(v != 0)
case 9:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModels
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthModels
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthModels
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Id = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipModels(dAtA[iNdEx:])

View file

@ -316,6 +316,7 @@ message Block {
repeated GroupOrder groupOrders = 12;
repeated ObjectOrder objectOrders = 13;
repeated anytype.model.RelationLink relationLinks = 5;
string TargetObjectId = 6;
message View {
string id = 1;
@ -324,12 +325,13 @@ message Block {
repeated Sort sorts = 4;
repeated Filter filters = 5;
repeated Relation relations = 6; // relations fields/columns options, also used to provide the order
string coverRelationKey = 7; // Relation used for cover in gallery
string coverRelationKey = 7; // Relation used for cover in gallery
bool hideIcon = 8; // Hide icon near name
Size cardSize = 9; // Gallery card size
bool coverFit = 10; // Image fits container
string groupRelationKey = 11; // Group view by this relationKey
bool groupBackgroundColors = 12; // Enable backgrounds in groups
bool groupBackgroundColors = 12; // Enable backgrounds in groups
int32 pageLimit = 13;
enum Type {
Table = 0;
@ -373,6 +375,8 @@ message Block {
string RelationKey = 1;
Type type = 2;
repeated google.protobuf.Value customOrder = 3;
RelationFormat format = 4;
bool includeTime = 5;
enum Type {
Asc = 0;
@ -382,6 +386,7 @@ message Block {
}
message Filter {
string id = 9;
Operator operator = 1; // looks not applicable?
string RelationKey = 2;
string relationProperty = 5;

View file

@ -4,6 +4,7 @@ import (
"archive/zip"
"bytes"
"context"
_ "embed"
"fmt"
"io"
"io/ioutil"
@ -35,8 +36,6 @@ import (
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/threads"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
_ "embed"
)
const CName = "builtinobjects"
@ -59,7 +58,7 @@ type BuiltinObjects interface {
}
type objectCreator interface {
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, relationIds []string, createState *state.State) (id string, newDetails *types.Struct, err error)
CreateSmartBlockFromState(ctx context.Context, sbType coresb.SmartBlockType, details *types.Struct, createState *state.State) (id string, newDetails *types.Struct, err error)
}
type builtinObjects struct {
@ -117,6 +116,11 @@ func (b *builtinObjects) inject(ctx context.Context) (err error) {
if err != nil {
return err
}
if sbt == smartblock.SmartBlockTypeSubObject {
// preserve original id for subobjects, it makes no sense to replace them and also it breaks the grouping
b.idsMap[id] = id
continue
}
tid, err := threads.ThreadCreateID(thread.AccessControlled, sbt)
if err != nil {
return err
@ -165,13 +169,16 @@ func (b *builtinObjects) createObject(ctx context.Context, rd io.ReadCloser) (er
}
m.Fields = &types.Struct{Fields: f}
f["analyticsContext"] = pbtypes.String(analyticsContext)
f["analyticsOriginalId"] = pbtypes.String(oldId)
if f["analyticsOriginalId"] == nil {
// in case we already have analyticsOriginalId do not update it
f["analyticsOriginalId"] = pbtypes.String(oldId)
}
st.Set(simple.New(m))
rels := relationutils.MigrateRelationModels(st.OldExtraRelations())
st.AddRelationLinks(rels...)
st.RemoveDetail(bundle.RelationKeyCreator.String(), bundle.RelationKeyLastModifiedBy.String())
st.RemoveDetail(bundle.RelationKeyCreator.String(), bundle.RelationKeyLastModifiedBy.String(), bundle.RelationKeyLastOpenedDate.String(), bundle.RelationKeyLinks.String())
st.SetLocalDetail(bundle.RelationKeyCreator.String(), pbtypes.String(addr.AnytypeProfileId))
st.SetLocalDetail(bundle.RelationKeyLastModifiedBy.String(), pbtypes.String(addr.AnytypeProfileId))
st.InjectDerivedDetails()
@ -225,7 +232,7 @@ func (b *builtinObjects) createObject(ctx context.Context, rd io.ReadCloser) (er
log.With("object", oldId).Errorf("failed to find relation %s: %s", k, err.Error())
continue
}
if rel.Format != model.RelationFormat_object {
if rel.Format != model.RelationFormat_object && rel.Format != model.RelationFormat_tag && rel.Format != model.RelationFormat_status {
continue
}
@ -250,7 +257,7 @@ func (b *builtinObjects) createObject(ctx context.Context, rd io.ReadCloser) (er
return err
}
_, _, err = b.objectCreator.CreateSmartBlockFromState(ctx, sbt, nil, nil, st)
_, _, err = b.objectCreator.CreateSmartBlockFromState(ctx, sbt, nil, st)
if isFavorite {
err = b.service.SetPageIsFavorite(pb.RpcObjectSetIsFavoriteRequest{ContextId: newId, IsFavorite: true})
if err != nil {

View file

@ -5,9 +5,7 @@ import (
"github.com/gogo/protobuf/types"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/slice"
)
var bytesPool = &sync.Pool{
@ -142,37 +140,3 @@ func CopyFilter(in *model.BlockContentDataviewFilter) (out *model.BlockContentDa
bytesPool.Put(buf)
return
}
func EventsToSliceChange(changes []*pb.EventBlockDataviewSliceChange) []slice.Change {
sliceOpMap := map[pb.EventBlockDataviewSliceOperation]slice.DiffOperation{
pb.EventBlockDataview_SliceOperationNone: slice.OperationNone,
pb.EventBlockDataview_SliceOperationAdd: slice.OperationAdd,
pb.EventBlockDataview_SliceOperationMove: slice.OperationMove,
pb.EventBlockDataview_SliceOperationRemove: slice.OperationRemove,
pb.EventBlockDataview_SliceOperationReplace: slice.OperationReplace,
}
var res []slice.Change
for _, eventCh := range changes {
res = append(res, slice.Change{Op: sliceOpMap[eventCh.Op], Ids: eventCh.Ids, AfterId: eventCh.AfterId})
}
return res
}
func SliceChangeToEvents(changes []slice.Change) []*pb.EventBlockDataviewSliceChange {
eventsOpMap := map[slice.DiffOperation]pb.EventBlockDataviewSliceOperation{
slice.OperationNone: pb.EventBlockDataview_SliceOperationNone,
slice.OperationAdd: pb.EventBlockDataview_SliceOperationAdd,
slice.OperationMove: pb.EventBlockDataview_SliceOperationMove,
slice.OperationRemove: pb.EventBlockDataview_SliceOperationRemove,
slice.OperationReplace: pb.EventBlockDataview_SliceOperationReplace,
}
var res []*pb.EventBlockDataviewSliceChange
for _, sliceCh := range changes {
res = append(res, &pb.EventBlockDataviewSliceChange{Op: eventsOpMap[sliceCh.Op], Ids: sliceCh.Ids, AfterId: sliceCh.AfterId})
}
return res
}

View file

@ -65,6 +65,13 @@ func IntList(ints ...int) *types.Value {
}
}
func NilToNullWrapper(v *types.Value) *types.Value {
if v == nil || v.Kind == nil {
return Null()
}
return v
}
func Bool(v bool) *types.Value {
return &types.Value{
Kind: &types.Value_BoolValue{BoolValue: v},
@ -197,11 +204,11 @@ func GetStringListValue(v *types.Value) []string {
return nil
}
for _, v := range list.ListValue.Values {
if _, ok = v.GetKind().(*types.Value_StringValue); ok {
if _, ok := v.GetKind().(*types.Value_StringValue); ok {
stringsSlice = append(stringsSlice, v.GetStringValue())
}
}
} else if val, ok := v.Kind.(*types.Value_StringValue); ok {
} else if val, ok := v.Kind.(*types.Value_StringValue); ok && val.StringValue != "" {
return []string{val.StringValue}
}
@ -421,3 +428,15 @@ func StructCompareIgnoreKeys(st1 *types.Struct, st2 *types.Struct, ignoreKeys []
}
return true
}
// ValueListWrapper wraps single value into the list. If value is already a list, it is returned as is.
// Null and struct values are not supported
func ValueListWrapper(value *types.Value) (*types.ListValue, error) {
switch v := value.Kind.(type) {
case *types.Value_ListValue:
return v.ListValue, nil
case *types.Value_StringValue, *types.Value_NumberValue, *types.Value_BoolValue:
return &types.ListValue{Values: []*types.Value{value}}, nil
}
return nil, fmt.Errorf("not supported type")
}

View file

@ -1,134 +1,294 @@
package slice
import (
"fmt"
"github.com/mb0/diff"
)
type DiffOperation int
const (
OperationNone DiffOperation = iota
OperationAdd
OperationMove
OperationRemove
OperationReplace
)
type Change struct {
Op DiffOperation
Ids []string
AfterId string
func StringIdentity[T ~string](x T) string {
return string(x)
}
type MixedInput struct {
A []string
B []string
func Equal[T comparable](a, b T) bool {
return a == b
}
func (m *MixedInput) Equal(a, b int) bool {
return m.A[a] == m.B[b]
type Change[T any] struct {
changeAdd *ChangeAdd[T]
changeRemove *ChangeRemove
changeMove *ChangeMove
changeReplace *ChangeReplace[T]
}
func Diff(origin, changed []string) []Change {
m := &MixedInput{
func (c Change[T]) String() string {
switch {
case c.changeAdd != nil:
return c.changeAdd.String()
case c.changeRemove != nil:
return c.changeRemove.String()
case c.changeMove != nil:
return c.changeMove.String()
case c.changeReplace != nil:
return c.changeReplace.String()
}
return ""
}
func MakeChangeAdd[T any](items []T, afterID string) Change[T] {
return Change[T]{
changeAdd: &ChangeAdd[T]{items, afterID},
}
}
func MakeChangeRemove[T any](ids []string) Change[T] {
return Change[T]{
changeRemove: &ChangeRemove{ids},
}
}
func MakeChangeMove[T any](ids []string, afterID string) Change[T] {
return Change[T]{
changeMove: &ChangeMove{ids, afterID},
}
}
func MakeChangeReplace[T any](item T, id string) Change[T] {
return Change[T]{
changeReplace: &ChangeReplace[T]{item, id},
}
}
func (c Change[T]) Len() int {
if c.changeAdd != nil {
return len(c.changeAdd.Items)
}
if c.changeRemove != nil {
return len(c.changeRemove.IDs)
}
if c.changeMove != nil {
return len(c.changeMove.IDs)
}
if c.changeReplace != nil {
return 1
}
return 0
}
func (c *Change[T]) Add() *ChangeAdd[T] {
return c.changeAdd
}
func (c *Change[T]) Remove() *ChangeRemove {
return c.changeRemove
}
func (c *Change[T]) Move() *ChangeMove {
return c.changeMove
}
func (c *Change[T]) Replace() *ChangeReplace[T] {
return c.changeReplace
}
type ChangeAdd[T any] struct {
Items []T
AfterID string
}
func (c ChangeAdd[T]) String() string {
return fmt.Sprintf("add %v after %s", c.Items, c.AfterID)
}
type ChangeMove struct {
IDs []string
AfterID string
}
func (c ChangeMove) String() string {
return fmt.Sprintf("move %v after %s", c.IDs, c.AfterID)
}
type ChangeRemove struct {
IDs []string
}
func (c ChangeRemove) String() string {
return fmt.Sprintf("remove %v", c.IDs)
}
type ChangeReplace[T any] struct {
Item T
ID string
}
func (c ChangeReplace[T]) String() string {
return fmt.Sprintf("replace %v after %s", c.Item, c.ID)
}
type MixedInput[T any] struct {
A []T
B []T
getID func(T) string
}
func (m *MixedInput[T]) Equal(a, b int) bool {
return m.getID(m.A[a]) == m.getID(m.B[b])
}
func Diff[T any](origin, changed []T, getID func(T) string, equal func(T, T) bool) []Change[T] {
m := &MixedInput[T]{
origin,
changed,
getID,
}
var result []Change
var result []Change[T]
changes := diff.Diff(len(m.A), len(m.B), m)
delMap := make(map[string]bool)
for _, c := range changes {
if c.Del > 0 {
for _, id := range m.A[c.A:c.A+c.Del] {
delMap[id] = true
}
delMap := make(map[string]struct{})
changedMap := make(map[string]T)
for _, c := range changed {
changedMap[getID(c)] = c
}
for _, c := range origin {
v, ok := changedMap[getID(c)]
if !ok {
continue
}
if !equal(c, v) {
result = append(result, MakeChangeReplace[T](v, getID(c)))
}
}
for _, c := range changes {
if c.Ins > 0 {
inserts := m.B[c.B:c.B+c.Ins]
afterId := ""
if c.A > 0 {
afterId = m.A[c.A-1]
}
var oneCh Change
for _, id := range inserts {
if delMap[id] { // move
if oneCh.Op != OperationMove {
if len(oneCh.Ids) > 0 {
result = append(result, oneCh)
}
oneCh = Change{Op: OperationMove, AfterId: afterId}
}
oneCh.Ids = append(oneCh.Ids, id)
delete(delMap, id)
} else { // insert new
if oneCh.Op != OperationAdd {
if len(oneCh.Ids) > 0 {
result = append(result, oneCh)
}
oneCh = Change{Op: OperationAdd, AfterId: afterId}
}
oneCh.Ids = append(oneCh.Ids, id)
}
afterId = id
}
if len(oneCh.Ids) > 0 {
result = append(result, oneCh)
}
if c.Del <= 0 {
continue
}
for _, it := range m.A[c.A : c.A+c.Del] {
delMap[getID(it)] = struct{}{}
}
}
for _, c := range changes {
if c.Ins <= 0 {
continue
}
inserts := m.B[c.B : c.B+c.Ins]
var afterID string
if c.A > 0 {
afterID = getID(m.A[c.A-1])
}
var oneCh Change[T]
for _, it := range inserts {
id := getID(it)
// If inserted item is found in deleted map then it is a Move operation
// nolint:nestif
if _, ok := delMap[id]; ok {
mv := oneCh.Move()
if mv == nil {
if oneCh.Len() > 0 {
result = append(result, oneCh)
}
oneCh = MakeChangeMove[T](nil, afterID)
mv = oneCh.Move()
}
mv.IDs = append(mv.IDs, getID(it))
delete(delMap, id)
} else { // insert new
add := oneCh.Add()
if add == nil {
if oneCh.Len() > 0 {
result = append(result, oneCh)
}
oneCh = MakeChangeAdd[T](nil, afterID)
add = oneCh.Add()
}
add.Items = append(add.Items, it)
}
afterID = id
}
if oneCh.Len() > 0 {
result = append(result, oneCh)
}
}
if len(delMap) > 0 { // remove
delIds := make([]string, 0, len(delMap))
delIDs := make([]string, 0, len(delMap))
for id := range delMap {
delIds = append(delIds, id)
delIDs = append(delIDs, id)
}
result = append(result, Change{Op: OperationRemove, Ids: delIds})
result = append(result, MakeChangeRemove[T](delIDs))
}
return result
}
func ApplyChanges(origin []string, changes []Change) []string {
result := make([]string, len(origin))
copy(result, origin)
func findPos[T any](s []T, getID func(T) string, id string) int {
for i, sv := range s {
if getID(sv) == id {
return i
}
}
return -1
}
func ApplyChanges[T any](origin []T, changes []Change[T], getID func(T) string) []T {
res := make([]T, len(origin))
copy(res, origin)
itemsMap := make(map[string]T, len(origin))
for _, it := range origin {
itemsMap[getID(it)] = it
}
for _, ch := range changes {
switch ch.Op {
case OperationAdd:
if add := ch.Add(); add != nil {
pos := -1
if ch.AfterId != "" {
pos = FindPos(result, ch.AfterId)
if pos < 0 {
if add.AfterID != "" {
pos = findPos(res, getID, add.AfterID)
}
res = Insert(res, pos+1, add.Items...)
}
if move := ch.Move(); move != nil {
res = FilterMut(res, func(id T) bool {
return FindPos(move.IDs, getID(id)) < 0
})
pos := -1
if move.AfterID != "" {
pos = findPos(res, getID, move.AfterID)
}
items := make([]T, 0, len(move.IDs))
for _, id := range move.IDs {
v, ok := itemsMap[id]
if !ok {
continue
}
items = append(items, v)
}
result = Insert(result, pos+1, ch.Ids...)
case OperationMove:
withoutMoved := Filter(result, func(id string) bool {
return FindPos(ch.Ids, id) < 0
res = Insert(res, pos+1, items...)
}
if rm := ch.Remove(); rm != nil {
res = FilterMut(res, func(id T) bool {
return FindPos(rm.IDs, getID(id)) < 0
})
pos := -1
if ch.AfterId != "" {
pos = FindPos(withoutMoved, ch.AfterId)
if pos < 0 {
continue
}
}
if replace := ch.Replace(); replace != nil {
itemsMap[replace.ID] = replace.Item
pos := findPos(res, getID, replace.ID)
if pos >= 0 && pos < len(res) {
res[pos] = replace.Item
}
result = Insert(withoutMoved, pos+1, ch.Ids...)
case OperationRemove:
result = Filter(result, func(id string) bool{
return FindPos(ch.Ids, id) < 0
})
case OperationReplace:
result = ch.Ids
}
}
return result
return res
}

View file

@ -1,57 +1,101 @@
package slice
import (
"math/rand"
"reflect"
"testing"
"testing/quick"
"time"
"github.com/globalsign/mgo/bson"
"github.com/stretchr/testify/assert"
"math/rand"
"testing"
"time"
)
func Test_Diff(t *testing.T) {
origin := []string{"000", "001", "002", "003", "004", "005", "006", "007", "008", "009"}
changed := []string{"000", "008", "001", "002", "003", "005", "006", "007", "009", "004"}
chs := Diff(origin, changed)
chs := Diff(origin, changed, StringIdentity[string], Equal[string])
assert.Equal(t, chs, []Change{
{Op: OperationMove, Ids: []string{"008"}, AfterId: "000"},
{Op: OperationMove, Ids: []string{"004"}, AfterId: "009"}},
)
assert.Equal(t, chs, []Change[string]{
MakeChangeMove[string]([]string{"008"}, "000"),
MakeChangeMove[string]([]string{"004"}, "009"),
})
}
type testItem struct {
id string
someField int
}
func Test_Replace(t *testing.T) {
origin := []testItem{
{"000", 100},
{"001", 101},
{"002", 102},
}
changed := []testItem{
{"001", 101},
{"002", 102},
{"000", 103},
}
getID := func(a testItem) string {
return a.id
}
chs := Diff(origin, changed, getID, func(a, b testItem) bool {
if a.id != b.id {
return false
}
return a.someField == b.someField
})
assert.Equal(t, []Change[testItem]{
MakeChangeReplace(testItem{"000", 103}, "000"),
MakeChangeMove[testItem]([]string{"000"}, "002"),
}, chs)
got := ApplyChanges(origin, chs, getID)
assert.Equal(t, changed, got)
}
func Test_ChangesApply(t *testing.T) {
origin := []string{"000", "001", "002", "003", "004", "005", "006", "007", "008", "009"}
changed := []string{"000", "008", "001", "002", "003", "005", "006", "007", "009", "004", "new"}
chs := Diff(origin, changed)
chs := Diff(origin, changed, StringIdentity[string], Equal[string])
res := ApplyChanges(origin, chs)
res := ApplyChanges(origin, chs, StringIdentity[string])
assert.Equal(t, changed, res)
}
type uniqueID string
func (id uniqueID) Generate(rand *rand.Rand, size int) reflect.Value {
return reflect.ValueOf(uniqueID(bson.NewObjectId().Hex()))
}
func Test_SameLength(t *testing.T) {
for i := 0; i < 10000; i++ {
l := randNum(5, 200)
origin := getRandArray(l)
changed := make([]string, len(origin))
f := func(origin []uniqueID) bool {
changed := make([]uniqueID, len(origin))
copy(changed, origin)
rand.Shuffle(len(changed),
func(i, j int) { changed[i], changed[j] = changed[j], changed[i] })
chs := Diff(origin, changed)
res := ApplyChanges(origin, chs)
chs := Diff(origin, changed, StringIdentity[uniqueID], Equal[uniqueID])
res := ApplyChanges(origin, chs, StringIdentity[uniqueID])
assert.Equal(t, res, changed)
return assert.Equal(t, res, changed)
}
assert.NoError(t, quick.Check(f, nil))
}
func Test_DifferentLength(t *testing.T) {
for i := 0; i < 10000; i++ {
l := randNum(5, 200)
origin := getRandArray(l)
changed := make([]string, len(origin))
f := func(origin []uniqueID) bool {
changed := make([]uniqueID, len(origin))
copy(changed, origin)
rand.Shuffle(len(changed),
func(i, j int) { changed[i], changed[j] = changed[j], changed[i] })
@ -73,28 +117,83 @@ func Test_DifferentLength(t *testing.T) {
continue
}
insIdx := randNum(0, l)
changed = Insert(changed, insIdx, []string{bson.NewObjectId().Hex()}...)
changed = Insert(changed, insIdx, []uniqueID{uniqueID(bson.NewObjectId().Hex())}...)
}
chs := Diff(origin, changed)
res := ApplyChanges(origin, chs)
chs := Diff(origin, changed, StringIdentity[uniqueID], Equal[uniqueID])
res := ApplyChanges(origin, chs, StringIdentity[uniqueID])
assert.Equal(t, res, changed)
return assert.Equal(t, res, changed)
}
assert.NoError(t, quick.Check(f, nil))
}
func randNum(min, max int) int{
// nolint:gosec
func randNum(min, max int) int {
if max <= min {
return max
}
rand.Seed(time.Now().UnixNano())
return rand.Intn(max - min) + min
return rand.Intn(max-min) + min
}
func getRandArray(len int) []string {
res := make([]string, len)
for i := 0; i < len; i++ {
res[i] = bson.NewObjectId().Hex()
// nolint:gosec
func genTestItems(count int) []*testItem {
items := make([]*testItem, count)
for i := 0; i < count; i++ {
items[i] = &testItem{id: bson.NewObjectId().Hex(), someField: rand.Intn(1000)}
}
return items
}
/*
Original
BenchmarkApplyChanges-8 3135 433618 ns/op 540552 B/op 558 allocs/op
Use FilterMut that reuses original slice capacity
BenchmarkApplyChanges-8 4134 346602 ns/op 90448 B/op 206 allocs/op
Remove dropping items in Move operations if afterID is not found (can cause data loss)
BenchmarkApplyChanges-8 2691 421134 ns/op 236785 B/op 385 allocs/op
*/
func BenchmarkApplyChanges(b *testing.B) {
const itemsCount = 100
items := genTestItems(itemsCount)
changes := make([]Change[*testItem], 500)
for i := 0; i < 500; i++ {
switch rand.Intn(4) {
case 0:
it := items[rand.Intn(itemsCount)]
newItem := &(*it)
newItem.someField = rand.Intn(1000)
changes[i] = MakeChangeReplace(newItem, it.id)
case 1:
idx := rand.Intn(itemsCount + 1)
var id string
// Let it be a chance to use empty AfterID
if idx < itemsCount {
id = items[idx].id
}
changes[i] = MakeChangeAdd(genTestItems(rand.Intn(2)+1), id)
case 2:
changes[i] = MakeChangeRemove[*testItem]([]string{items[rand.Intn(itemsCount)].id})
case 3:
idx := rand.Intn(itemsCount + 1)
var id string
// Let it be a chance to use empty AfterID
if idx < itemsCount {
id = items[idx].id
}
changes[i] = MakeChangeMove[*testItem]([]string{items[rand.Intn(itemsCount)].id}, id)
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = ApplyChanges(items, changes, func(a *testItem) string {
return a.id
})
}
return res
}

View file

@ -42,7 +42,7 @@ func DifferenceRemovedAdded(a, b []string) (removed []string, added []string) {
return
}
func FindPos(s []string, v string) int {
func FindPos[T comparable](s []T, v T) int {
for i, sv := range s {
if sv == v {
return i
@ -51,6 +51,15 @@ func FindPos(s []string, v string) int {
return -1
}
func Find[T comparable](s []T, cond func(T) bool) int {
for i, sv := range s {
if cond(sv) {
return i
}
}
return -1
}
// Difference returns the elements in `a` that aren't in `b`.
func Difference(a, b []string) []string {
var diff = make([]string, 0, len(a))
@ -62,7 +71,7 @@ func Difference(a, b []string) []string {
return diff
}
func Insert(s []string, pos int, v ...string) []string {
func Insert[T any](s []T, pos int, v ...T) []T {
if len(s) <= pos {
return append(s, v...)
}
@ -73,7 +82,7 @@ func Insert(s []string, pos int, v ...string) []string {
}
// Remove reuses provided slice capacity. Provided s slice should not be used after without reassigning to the func return!
func Remove(s []string, v string) []string {
func Remove[T comparable](s []T, v T) []T {
var n int
for _, x := range s {
if x != v {
@ -84,8 +93,30 @@ func Remove(s []string, v string) []string {
return s[:n]
}
func Filter(vals []string, cond func(string) bool) []string {
var result = make([]string, 0, len(vals))
// RemoveIndex reuses provided slice capacity. Provided s slice should not be used after without reassigning to the func return!
func RemoveIndex[T any](s []T, idx int) []T {
var n int
for i, x := range s {
if i != idx {
s[n] = x
n++
}
}
return s[:n]
}
func Filter[T any](vals []T, cond func(T) bool) []T {
var result = make([]T, 0, len(vals))
for i := range vals {
if cond(vals[i]) {
result = append(result, vals[i])
}
}
return result
}
func FilterMut[T any](vals []T, cond func(T) bool) []T {
result := vals[:0]
for i := range vals {
if cond(vals[i]) {
result = append(result, vals[i])

15
util/time/time.go Normal file
View file

@ -0,0 +1,15 @@
package time
import (
"time"
"github.com/gogo/protobuf/types"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
)
func CutValueToDay(val *types.Value) *types.Value {
t := time.Unix(int64(val.GetNumberValue()), 0)
roundTime := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
return pbtypes.Int64(roundTime.Unix())
}