Merge remote-tracking branch 'github/master'

pull/479/head
wuxingzhong 5 years ago
commit 39fde7f628
  1. 2
      go.mod
  2. 8
      go.sum
  3. 233
      pkg/conf/paladin/file.go
  4. 53
      pkg/conf/paladin/file_test.go
  5. 13
      pkg/naming/discovery/discovery.go
  6. 6
      pkg/net/http/blademaster/client.go
  7. 4
      pkg/net/http/blademaster/logger.go
  8. 10
      pkg/net/http/blademaster/metrics.go
  9. 2
      pkg/net/http/blademaster/ratelimit.go
  10. 7
      pkg/stat/metric/rolling_policy.go
  11. 67
      pkg/stat/metric/rolling_policy_test.go
  12. 11
      tool/kratos-gen-project/main.go
  13. 12
      tool/kratos-gen-project/new.go
  14. 126
      tool/kratos-gen-project/packrd/packed-packr.go
  15. 9
      tool/kratos-gen-project/project.go
  16. 18
      tool/kratos-gen-project/templates/all/api/api.proto
  17. 11
      tool/kratos-gen-project/templates/all/go.mod.tmpl
  18. 14
      tool/kratos-gen-project/templates/all/internal/dao/dao.go.tmpl
  19. 40
      tool/kratos-gen-project/templates/all/internal/dao/dao_test.go.tmpl
  20. 15
      tool/kratos-gen-project/templates/all/internal/dao/db.go.tmpl
  21. 15
      tool/kratos-gen-project/templates/all/internal/dao/mc.go.tmpl
  22. 15
      tool/kratos-gen-project/templates/all/internal/dao/redis.go.tmpl
  23. 13
      tool/kratos-gen-project/templates/all/internal/dao/wire.go.tmpl
  24. 1
      tool/kratos-gen-project/templates/all/internal/di/app.go.tmpl
  25. 9
      tool/kratos-gen-project/templates/all/internal/di/wire.go.tmpl
  26. 15
      tool/kratos-gen-project/templates/all/internal/server/grpc/server.go.tmpl
  27. 17
      tool/kratos-gen-project/templates/all/internal/server/http/server.go.tmpl
  28. 7
      tool/kratos-gen-project/templates/all/internal/service/service.go.tmpl
  29. 11
      tool/kratos-gen-project/templates/all/test/0_db.sql
  30. 3
      tool/kratos-gen-project/templates/all/test/1_data.sql
  31. 3
      tool/kratos-gen-project/templates/all/test/application.toml
  32. 8
      tool/kratos-gen-project/templates/all/test/db.toml
  33. 6
      tool/kratos-gen-project/templates/all/test/docker-compose.yaml
  34. 3
      tool/kratos-gen-project/templates/all/test/grpc.toml
  35. 3
      tool/kratos-gen-project/templates/all/test/http.toml
  36. 10
      tool/kratos-gen-project/templates/all/test/memcache.toml
  37. 10
      tool/kratos-gen-project/templates/all/test/redis.toml
  38. 2
      tool/kratos-gen-project/templates/grpc/OWNERS
  39. 18
      tool/kratos-gen-project/templates/grpc/api/api.proto
  40. 11
      tool/kratos-gen-project/templates/grpc/go.mod.tmpl
  41. 14
      tool/kratos-gen-project/templates/grpc/internal/dao/dao.go.tmpl
  42. 40
      tool/kratos-gen-project/templates/grpc/internal/dao/dao_test.go.tmpl
  43. 15
      tool/kratos-gen-project/templates/grpc/internal/dao/db.go.tmpl
  44. 15
      tool/kratos-gen-project/templates/grpc/internal/dao/mc.go.tmpl
  45. 15
      tool/kratos-gen-project/templates/grpc/internal/dao/redis.go.tmpl
  46. 13
      tool/kratos-gen-project/templates/grpc/internal/dao/wire.go.tmpl
  47. 1
      tool/kratos-gen-project/templates/grpc/internal/di/app.go.tmpl
  48. 9
      tool/kratos-gen-project/templates/grpc/internal/di/wire.go.tmpl
  49. 15
      tool/kratos-gen-project/templates/grpc/internal/server/grpc/server.go.tmpl
  50. 7
      tool/kratos-gen-project/templates/grpc/internal/service/service.go.tmpl
  51. 11
      tool/kratos-gen-project/templates/grpc/test/0_db.sql
  52. 3
      tool/kratos-gen-project/templates/grpc/test/1_data.sql
  53. 3
      tool/kratos-gen-project/templates/grpc/test/application.toml
  54. 8
      tool/kratos-gen-project/templates/grpc/test/db.toml
  55. 6
      tool/kratos-gen-project/templates/grpc/test/docker-compose.yaml
  56. 3
      tool/kratos-gen-project/templates/grpc/test/grpc.toml
  57. 10
      tool/kratos-gen-project/templates/grpc/test/memcache.toml
  58. 10
      tool/kratos-gen-project/templates/grpc/test/redis.toml
  59. 18
      tool/kratos-gen-project/templates/http/api/api.proto
  60. 11
      tool/kratos-gen-project/templates/http/go.mod.tmpl
  61. 14
      tool/kratos-gen-project/templates/http/internal/dao/dao.go.tmpl
  62. 40
      tool/kratos-gen-project/templates/http/internal/dao/dao_test.go.tmpl
  63. 15
      tool/kratos-gen-project/templates/http/internal/dao/db.go.tmpl
  64. 15
      tool/kratos-gen-project/templates/http/internal/dao/mc.go.tmpl
  65. 15
      tool/kratos-gen-project/templates/http/internal/dao/redis.go.tmpl
  66. 13
      tool/kratos-gen-project/templates/http/internal/dao/wire.go.tmpl
  67. 1
      tool/kratos-gen-project/templates/http/internal/di/app.go.tmpl
  68. 11
      tool/kratos-gen-project/templates/http/internal/di/wire.go.tmpl
  69. 17
      tool/kratos-gen-project/templates/http/internal/server/http/server.go.tmpl
  70. 7
      tool/kratos-gen-project/templates/http/internal/service/service.go.tmpl
  71. 11
      tool/kratos-gen-project/templates/http/test/0_db.sql
  72. 3
      tool/kratos-gen-project/templates/http/test/1_data.sql
  73. 3
      tool/kratos-gen-project/templates/http/test/application.toml
  74. 8
      tool/kratos-gen-project/templates/http/test/db.toml
  75. 6
      tool/kratos-gen-project/templates/http/test/docker-compose.yaml
  76. 3
      tool/kratos-gen-project/templates/http/test/http.toml
  77. 10
      tool/kratos-gen-project/templates/http/test/memcache.toml
  78. 10
      tool/kratos-gen-project/templates/http/test/redis.toml
  79. 22
      tool/kratos-gen-project/testdata/test_in_gomod.sh
  80. 43
      tool/kratos-gen-project/testdata/test_not_in_gomod.sh
  81. 2
      tool/kratos/tool_index.go
  82. 4
      tool/kratos/version.go

@ -54,7 +54,7 @@ require (
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd // indirect golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd // indirect
golang.org/x/tools v0.0.0-20191105231337-689d0f08e67a golang.org/x/tools v0.0.0-20191105231337-689d0f08e67a
google.golang.org/appengine v1.6.1 // indirect google.golang.org/appengine v1.6.1 // indirect
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 google.golang.org/genproto v0.0.0-20191216205247-b31c10ee225f
google.golang.org/grpc v1.24.0 google.golang.org/grpc v1.24.0
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v9 v9.29.1 gopkg.in/go-playground/validator.v9 v9.29.1

@ -315,8 +315,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59 h1:PyXRxSVbvzDGuqYXjHndV7xDzJ7w2K8KD9Ef8GB7KOE= golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59 h1:PyXRxSVbvzDGuqYXjHndV7xDzJ7w2K8KD9Ef8GB7KOE=
golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -364,8 +362,6 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8 h1:41hwlulw1prEMBxLQSlMSux1zxJf07B3WPsdjJlKZxE= golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8 h1:41hwlulw1prEMBxLQSlMSux1zxJf07B3WPsdjJlKZxE=
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII= golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII=
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -396,8 +392,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 h1:4HYDjxeNXAOTv3o1N2tjo8UUSlhQgAD52FVkwxnWgM8= google.golang.org/genproto v0.0.0-20191216205247-b31c10ee225f h1:0RYv5T9ZdroAqqfM2taEB0nJrArv0X1JpIdgUmY4xg8=
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216205247-b31c10ee225f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk= google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk=

@ -2,80 +2,122 @@ package paladin
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"strings"
"sync" "sync"
"time" "time"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
) )
const (
defaultChSize = 10
)
var _ Client = &file{} var _ Client = &file{}
type watcher struct { // file is file config client.
keys []string type file struct {
C chan Event values *Map
rawVal map[string]*Value
watchChs map[string][]chan Event
mx sync.Mutex
wg sync.WaitGroup
base string
done chan struct{}
} }
func newWatcher(keys []string) *watcher { func isHiddenFile(name string) bool {
return &watcher{keys: keys, C: make(chan Event, 5)} // TODO: support windows.
return strings.HasPrefix(filepath.Base(name), ".")
} }
func (w *watcher) HasKey(key string) bool { func readAllPaths(base string) ([]string, error) {
if len(w.keys) == 0 { fi, err := os.Stat(base)
return true if err != nil {
return nil, fmt.Errorf("check local config file fail! error: %s", err)
} }
for _, k := range w.keys { // dirs or file to paths
if KeyNamed(k) == key { var paths []string
return true if fi.IsDir() {
files, err := ioutil.ReadDir(base)
if err != nil {
return nil, fmt.Errorf("read dir %s error: %s", base, err)
}
for _, file := range files {
if !file.IsDir() && !isHiddenFile(file.Name()) {
paths = append(paths, path.Join(base, file.Name()))
}
} }
} else {
paths = append(paths, base)
} }
return false return paths, nil
} }
func (w *watcher) Handle(event Event) { func loadValuesFromPaths(paths []string) (map[string]*Value, error) {
select { // laod config file to values
case w.C <- event: var err error
default: values := make(map[string]*Value, len(paths))
log.Printf("paladin: event channel full discard file %s update event", event.Key) for _, fpath := range paths {
if values[path.Base(fpath)], err = loadValue(fpath); err != nil {
return nil, err
}
} }
return values, nil
} }
// file is file config client. func loadValue(fpath string) (*Value, error) {
type file struct { data, err := ioutil.ReadFile(fpath)
values *Map if err != nil {
wmu sync.RWMutex return nil, err
notify *fsnotify.Watcher }
watchers map[*watcher]struct{} content := string(data)
return &Value{val: content, raw: content}, nil
} }
// NewFile new a config file client. // NewFile new a config file client.
// conf = /data/conf/app/ // conf = /data/conf/app/
// conf = /data/conf/app/xxx.toml // conf = /data/conf/app/xxx.toml
func NewFile(base string) (Client, error) { func NewFile(base string) (Client, error) {
// paltform slash
base = filepath.FromSlash(base) base = filepath.FromSlash(base)
raws, err := loadValues(base)
paths, err := readAllPaths(base)
if err != nil { if err != nil {
return nil, err return nil, err
} }
notify, err := fsnotify.NewWatcher() if len(paths) == 0 {
return nil, fmt.Errorf("empty config path")
}
rawVal, err := loadValuesFromPaths(paths)
if err != nil { if err != nil {
return nil, err return nil, err
} }
values := new(Map)
values.Store(raws) valMap := &Map{}
f := &file{ valMap.Store(rawVal)
values: values, fc := &file{
notify: notify, values: valMap,
watchers: make(map[*watcher]struct{}), rawVal: rawVal,
watchChs: make(map[string][]chan Event),
base: base,
done: make(chan struct{}, 1),
} }
go f.watchproc(base)
return f, nil fc.wg.Add(1)
go fc.daemon()
return fc, nil
} }
// Get return value by key. // Get return value by key.
@ -88,109 +130,74 @@ func (f *file) GetAll() *Map {
return f.values return f.values
} }
// WatchEvent watch with the specified keys. // WatchEvent watch multi key.
func (f *file) WatchEvent(ctx context.Context, keys ...string) <-chan Event { func (f *file) WatchEvent(ctx context.Context, keys ...string) <-chan Event {
w := newWatcher(keys) f.mx.Lock()
f.wmu.Lock() defer f.mx.Unlock()
f.watchers[w] = struct{}{} ch := make(chan Event, defaultChSize)
f.wmu.Unlock() for _, key := range keys {
return w.C f.watchChs[key] = append(f.watchChs[key], ch)
}
return ch
} }
// Close close watcher. // Close close watcher.
func (f *file) Close() error { func (f *file) Close() error {
if err := f.notify.Close(); err != nil { f.done <- struct{}{}
return err f.wg.Wait()
}
f.wmu.RLock()
for w := range f.watchers {
close(w.C)
}
f.wmu.RUnlock()
return nil return nil
} }
// file config daemon to watch file modification // file config daemon to watch file modification
func (f *file) watchproc(base string) { func (f *file) daemon() {
if err := f.notify.Add(base); err != nil { defer f.wg.Done()
log.Printf("paladin: create fsnotify for base path %s fail %s, reload function will lose efficacy", base, err) fswatcher, err := fsnotify.NewWatcher()
if err != nil {
log.Printf("create file watcher fail! reload function will lose efficacy error: %s", err)
return
}
if err = fswatcher.Add(f.base); err != nil {
log.Printf("create fsnotify for base path %s fail %s, reload function will lose efficacy", f.base, err)
return return
} }
log.Printf("paladin: start watch config: %s", base) log.Printf("start watch filepath: %s", f.base)
for event := range f.notify.Events { for event := range fswatcher.Events {
switch event.Op {
// use vim edit config will trigger rename // use vim edit config will trigger rename
switch { case fsnotify.Write, fsnotify.Create:
case event.Op&fsnotify.Write == fsnotify.Write, event.Op&fsnotify.Create == fsnotify.Create: f.reloadFile(event.Name)
if err := f.reloadFile(event.Name); err != nil { case fsnotify.Chmod:
log.Printf("paladin: load file: %s error: %s, skipped", event.Name, err)
}
default: default:
log.Printf("paladin: unsupport event %s ingored", event) log.Printf("unsupport event %s ingored", event)
} }
} }
} }
func (f *file) reloadFile(fpath string) (err error) { func (f *file) reloadFile(name string) {
if isHiddenFile(name) {
return
}
// NOTE: in some case immediately read file content after receive event // NOTE: in some case immediately read file content after receive event
// will get old content, sleep 100ms make sure get correct content. // will get old content, sleep 100ms make sure get correct content.
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
value, err := loadValue(fpath) key := filepath.Base(name)
val, err := loadValue(name)
if err != nil { if err != nil {
log.Printf("load file %s error: %s, skipped", name, err)
return return
} }
key := KeyNamed(path.Base(fpath)) f.rawVal[key] = val
raws := f.values.Load() f.values.Store(f.rawVal)
raws[key] = value
f.values.Store(raws)
f.wmu.RLock()
n := 0
for w := range f.watchers {
if w.HasKey(key) {
n++
w.Handle(Event{Event: EventUpdate, Key: key, Value: value.raw})
}
}
f.wmu.RUnlock()
log.Printf("paladin: reload config: %s events: %d\n", key, n)
return
}
func loadValues(base string) (map[string]*Value, error) { f.mx.Lock()
fi, err := os.Stat(base) chs := f.watchChs[key]
if err != nil { f.mx.Unlock()
return nil, fmt.Errorf("paladin: check local config file fail! error: %s", err)
}
var paths []string
if fi.IsDir() {
files, err := ioutil.ReadDir(base)
if err != nil {
return nil, fmt.Errorf("paladin: read dir %s error: %s", base, err)
}
for _, file := range files {
if !file.IsDir() && (file.Mode()&os.ModeSymlink) != os.ModeSymlink {
paths = append(paths, path.Join(base, file.Name()))
}
}
} else {
paths = append(paths, base)
}
if len(paths) == 0 {
return nil, errors.New("empty config path")
}
values := make(map[string]*Value, len(paths))
for _, fpath := range paths {
if values[path.Base(fpath)], err = loadValue(fpath); err != nil {
return nil, err
}
}
return values, nil
}
func loadValue(name string) (*Value, error) { for _, ch := range chs {
data, err := ioutil.ReadFile(name) select {
if err != nil { case ch <- Event{Event: EventUpdate, Value: val.raw}:
return nil, err default:
log.Printf("event channel full discard file %s update event", name)
}
} }
content := string(data)
return &Value{val: content, raw: content}, nil
} }

@ -82,9 +82,8 @@ func TestFileEvent(t *testing.T) {
cli, err := NewFile(path) cli, err := NewFile(path)
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, cli) assert.NotNil(t, cli)
time.Sleep(time.Millisecond * 100)
ch := cli.WatchEvent(context.Background(), "test.toml", "abc.toml") ch := cli.WatchEvent(context.Background(), "test.toml", "abc.toml")
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond)
ioutil.WriteFile(path+"test.toml", []byte(`hello`), 0644) ioutil.WriteFile(path+"test.toml", []byte(`hello`), 0644)
timeout := time.NewTimer(time.Second) timeout := time.NewTimer(time.Second)
select { select {
@ -94,4 +93,54 @@ func TestFileEvent(t *testing.T) {
assert.Equal(t, EventUpdate, ev.Event) assert.Equal(t, EventUpdate, ev.Event)
assert.Equal(t, "hello", ev.Value) assert.Equal(t, "hello", ev.Value)
} }
ioutil.WriteFile(path+"abc.toml", []byte(`test`), 0644)
select {
case <-timeout.C:
t.Fatalf("run test timeout")
case ev := <-ch:
assert.Equal(t, EventUpdate, ev.Event)
assert.Equal(t, "test", ev.Value)
}
content1, _ := cli.Get("test.toml").String()
assert.Equal(t, "hello", content1)
content2, _ := cli.Get("abc.toml").String()
assert.Equal(t, "test", content2)
}
func TestHiddenFile(t *testing.T) {
path := "/tmp/test_hidden_event/"
assert.Nil(t, os.MkdirAll(path, 0700))
assert.Nil(t, ioutil.WriteFile(path+"test.toml", []byte(`hello`), 0644))
assert.Nil(t, ioutil.WriteFile(path+".abc.toml", []byte(`
text = "hello"
number = 100
`), 0644))
// test client
cli, err := NewFile(path)
assert.Nil(t, err)
assert.NotNil(t, cli)
cli.WatchEvent(context.Background(), "test.toml")
time.Sleep(time.Millisecond)
ioutil.WriteFile(path+".abc.toml", []byte(`hello`), 0644)
time.Sleep(time.Second)
content1, _ := cli.Get("test.toml").String()
assert.Equal(t, "hello", content1)
_, err = cli.Get(".abc.toml").String()
assert.NotNil(t, err)
}
func TestOneLevelSymbolicFile(t *testing.T) {
path := "/tmp/test_symbolic_link/"
path2 := "/tmp/test_symbolic_link/configs/"
assert.Nil(t, os.MkdirAll(path2, 0700))
assert.Nil(t, ioutil.WriteFile(path+"test.toml", []byte(`hello`), 0644))
assert.Nil(t, os.Symlink(path+"test.toml", path2+"test.toml.ln"))
// test client
cli, err := NewFile(path2)
assert.Nil(t, err)
assert.NotNil(t, cli)
content, _ := cli.Get("test.toml.ln").String()
assert.Equal(t, "hello", content)
os.Remove(path+"test.toml")
os.Remove(path2+"test.toml.ln")
} }

@ -276,9 +276,18 @@ func (r *Resolve) Fetch(ctx context.Context) (ins *naming.InstancesInfo, ok bool
app, ok := r.d.apps[r.id] app, ok := r.d.apps[r.id]
r.d.mutex.RUnlock() r.d.mutex.RUnlock()
if ok { if ok {
ins, ok = app.zoneIns.Load().(*naming.InstancesInfo) var appIns *naming.InstancesInfo
appIns, ok = app.zoneIns.Load().(*naming.InstancesInfo)
ins = new(naming.InstancesInfo)
ins.LastTs = appIns.LastTs
ins.Scheduler = appIns.Scheduler
if r.opt.Filter != nil { if r.opt.Filter != nil {
ins.Instances = r.opt.Filter(ins.Instances) ins.Instances = r.opt.Filter(appIns.Instances)
} else {
ins.Instances = make(map[string][]*naming.Instance)
for zone, in := range appIns.Instances {
ins.Instances[zone] = in
}
} }
if r.opt.Scheduler != nil { if r.opt.Scheduler != nil {
ins.Instances[r.opt.ClientZone] = r.opt.Scheduler(ins) ins.Instances[r.opt.ClientZone] = r.opt.Scheduler(ins)

@ -213,16 +213,16 @@ func (client *Client) Raw(c context.Context, req *xhttp.Request, v ...string) (b
brk := client.breaker.Get(uri) brk := client.breaker.Get(uri)
if err = brk.Allow(); err != nil { if err = brk.Allow(); err != nil {
code = "breaker" code = "breaker"
_metricClientReqCodeTotal.Inc(uri, code) _metricClientReqCodeTotal.Inc(uri, req.Method, code)
return return
} }
defer client.onBreaker(brk, &err) defer client.onBreaker(brk, &err)
// stat // stat
now := time.Now() now := time.Now()
defer func() { defer func() {
_metricClientReqDur.Observe(int64(time.Since(now)/time.Millisecond), uri) _metricClientReqDur.Observe(int64(time.Since(now)/time.Millisecond), uri, req.Method)
if code != "" { if code != "" {
_metricClientReqCodeTotal.Inc(uri, code) _metricClientReqCodeTotal.Inc(uri, req.Method, code)
} }
}() }()
// get config // get config

@ -35,8 +35,8 @@ func Logger() HandlerFunc {
} }
if len(c.RoutePath) > 0 { if len(c.RoutePath) > 0 {
_metricServerReqCodeTotal.Inc(c.RoutePath[1:], caller, strconv.FormatInt(int64(cerr.Code()), 10)) _metricServerReqCodeTotal.Inc(c.RoutePath[1:], caller, req.Method, strconv.FormatInt(int64(cerr.Code()), 10))
_metricServerReqDur.Observe(int64(dt/time.Millisecond), c.RoutePath[1:], caller) _metricServerReqDur.Observe(int64(dt/time.Millisecond), c.RoutePath[1:], caller, req.Method)
} }
lf := log.Infov lf := log.Infov

@ -13,7 +13,7 @@ var (
Subsystem: "requests", Subsystem: "requests",
Name: "duration_ms", Name: "duration_ms",
Help: "http server requests duration(ms).", Help: "http server requests duration(ms).",
Labels: []string{"path", "caller"}, Labels: []string{"path", "caller", "method"},
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000}, Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000},
}) })
_metricServerReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{ _metricServerReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
@ -21,21 +21,21 @@ var (
Subsystem: "requests", Subsystem: "requests",
Name: "code_total", Name: "code_total",
Help: "http server requests error count.", Help: "http server requests error count.",
Labels: []string{"path", "caller", "code"}, Labels: []string{"path", "caller", "method", "code"},
}) })
_metricServerBBR = metric.NewCounterVec(&metric.CounterVecOpts{ _metricServerBBR = metric.NewCounterVec(&metric.CounterVecOpts{
Namespace: serverNamespace, Namespace: serverNamespace,
Subsystem: "", Subsystem: "",
Name: "bbr_total", Name: "bbr_total",
Help: "http server bbr total.", Help: "http server bbr total.",
Labels: []string{"url"}, Labels: []string{"url", "method"},
}) })
_metricClientReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{ _metricClientReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
Namespace: clientNamespace, Namespace: clientNamespace,
Subsystem: "requests", Subsystem: "requests",
Name: "duration_ms", Name: "duration_ms",
Help: "http client requests duration(ms).", Help: "http client requests duration(ms).",
Labels: []string{"path"}, Labels: []string{"path", "method"},
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000}, Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000},
}) })
_metricClientReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{ _metricClientReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
@ -43,6 +43,6 @@ var (
Subsystem: "requests", Subsystem: "requests",
Name: "code_total", Name: "code_total",
Help: "http client requests code count.", Help: "http client requests code count.",
Labels: []string{"path", "code"}, Labels: []string{"path", "method", "code"},
}) })
) )

@ -39,7 +39,7 @@ func (b *RateLimiter) Limit() HandlerFunc {
limiter := b.group.Get(uri) limiter := b.group.Get(uri)
done, err := limiter.Allow(c) done, err := limiter.Allow(c)
if err != nil { if err != nil {
_metricServerBBR.Inc(uri) _metricServerBBR.Inc(uri, c.Request.Method)
c.JSON(nil, err) c.JSON(nil, err)
c.Abort() c.Abort()
return return

@ -38,7 +38,7 @@ func NewRollingPolicy(window *Window, opts RollingPolicyOpts) *RollingPolicy {
func (r *RollingPolicy) timespan() int { func (r *RollingPolicy) timespan() int {
v := int(time.Since(r.lastAppendTime) / r.bucketDuration) v := int(time.Since(r.lastAppendTime) / r.bucketDuration)
if v < r.size && v > -1 { // maybe time backwards if v > -1 { // maybe time backwards
return v return v
} }
return r.size return r.size
@ -48,9 +48,13 @@ func (r *RollingPolicy) add(f func(offset int, val float64), val float64) {
r.mu.Lock() r.mu.Lock()
timespan := r.timespan() timespan := r.timespan()
if timespan > 0 { if timespan > 0 {
r.lastAppendTime = r.lastAppendTime.Add(time.Duration(timespan * int(r.bucketDuration)))
offset := r.offset offset := r.offset
// reset the expired buckets // reset the expired buckets
s := offset + 1 s := offset + 1
if timespan > r.size {
timespan = r.size
}
e, e1 := s+timespan, 0 // e: reset offset must start from offset+1 e, e1 := s+timespan, 0 // e: reset offset must start from offset+1
if e > r.size { if e > r.size {
e1 = e - r.size e1 = e - r.size
@ -65,7 +69,6 @@ func (r *RollingPolicy) add(f func(offset int, val float64), val float64) {
offset = i offset = i
} }
r.offset = offset r.offset = offset
r.lastAppendTime = time.Now()
} }
f(r.offset, val) f(r.offset, val)
r.mu.Unlock() r.mu.Unlock()

@ -0,0 +1,67 @@
package metric
import (
"fmt"
"math/rand"
"testing"
"time"
)
func GetRollingPolicy() *RollingPolicy {
w := NewWindow(WindowOpts{Size: 10})
return NewRollingPolicy(w, RollingPolicyOpts{BucketDuration: 300 * time.Millisecond})
}
func Handler(t *testing.T, table []map[string][]int) {
for _, hm := range table {
var totalTs, lastOffset int
offsetAndPoints := hm["offsetAndPoints"]
timeSleep := hm["timeSleep"]
policy := GetRollingPolicy()
for i, n := range timeSleep {
totalTs += n
time.Sleep(time.Duration(n) * time.Millisecond)
policy.Add(1)
offset, points := offsetAndPoints[2*i], offsetAndPoints[2*i+1]
if int(policy.window.window[offset].Points[0]) != points {
t.Errorf("error, time since last append: %vms, last offset: %v", totalTs, lastOffset)
}
lastOffset = offset
}
}
}
func TestRollingPolicy_Add(t *testing.T) {
rand.Seed(time.Now().Unix())
// test add after 400ms and 601ms relative to the policy created time
policy := GetRollingPolicy()
time.Sleep(400 * time.Millisecond)
policy.Add(1)
time.Sleep(201 * time.Millisecond)
policy.Add(1)
for _, b := range policy.window.window {
fmt.Println(b.Points)
}
if int(policy.window.window[1].Points[0]) != 1 {
t.Errorf("error, time since last append: %vms, last offset: %v", 300, 0)
}
if int(policy.window.window[2].Points[0]) != 1 {
t.Errorf("error, time since last append: %vms, last offset: %v", 301, 0)
}
// test func timespan return real span
table := []map[string][]int{
{
"timeSleep": []int{294, 3200},
"offsetAndPoints": []int{0, 1, 0, 1},
},
{
"timeSleep": []int{305, 3200, 6400},
"offsetAndPoints": []int{1, 1, 1, 1, 1, 1},
},
}
Handler(t, table)
}

@ -1,7 +1,6 @@
package main package main
import ( import (
"fmt"
"os" "os"
"strings" "strings"
@ -11,7 +10,7 @@ import (
var appHelpTemplate = `{{if .Usage}}{{.Usage}}{{end}} var appHelpTemplate = `{{if .Usage}}{{.Usage}}{{end}}
USAGE: USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} kratos new {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
VERSION: VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}} {{.Version}}{{end}}{{end}}{{if .Description}}
@ -35,7 +34,7 @@ func main() {
app := cli.NewApp() app := cli.NewApp()
app.Name = "" app.Name = ""
app.Usage = "kratos 新项目创建工具" app.Usage = "kratos 新项目创建工具"
app.UsageText = "name [options]" app.UsageText = "项目名 [options]"
app.HideVersion = true app.HideVersion = true
app.CustomAppHelpTemplate = appHelpTemplate app.CustomAppHelpTemplate = appHelpTemplate
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
@ -53,7 +52,7 @@ func main() {
cli.BoolFlag{ cli.BoolFlag{
Name: "grpc", Name: "grpc",
Usage: "只使用grpc 不使用http", Usage: "只使用grpc 不使用http",
Destination: &p.onlyHTTP, Destination: &p.onlyGRPC,
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "proto", Name: "proto",
@ -63,8 +62,8 @@ func main() {
}, },
} }
if len(os.Args) < 2 || strings.HasPrefix(os.Args[1], "-") { if len(os.Args) < 2 || strings.HasPrefix(os.Args[1], "-") {
fmt.Fprintf(os.Stderr, "未填写项目名称\n") app.Run([]string{"-h"})
os.Exit(-1) return
} }
p.Name = os.Args[1] p.Name = os.Args[1]
app.Action = runNew app.Action = runNew

@ -7,7 +7,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/bilibili/kratos/tool/pkg" common "github.com/bilibili/kratos/tool/pkg"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -43,8 +44,13 @@ func modPath(p string) string {
for { for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
content, _ := ioutil.ReadFile(filepath.Join(dir, "go.mod")) content, _ := ioutil.ReadFile(filepath.Join(dir, "go.mod"))
mod := pkg.RegexpReplace(`module\s+(?P<name>[\S]+)`, string(content), "$name") mod := common.RegexpReplace(`module\s+(?P<name>[\S]+)`, string(content), "$name")
return fmt.Sprintf("%s/%s/", mod, strings.TrimPrefix(filepath.Dir(p), dir+string(os.PathSeparator))) name := strings.TrimPrefix(filepath.Dir(p), dir)
name = strings.TrimPrefix(name, string(os.PathSeparator))
if name == "" {
return fmt.Sprintf("%s/", mod)
}
return fmt.Sprintf("%s/%s/", mod, name)
} }
parent := filepath.Dir(dir) parent := filepath.Dir(dir)
if dir == parent { if dir == parent {

@ -14,73 +14,101 @@ var _ = func() error {
const gk = "314eeeb23d475df0cf6cd2642a1621a3" const gk = "314eeeb23d475df0cf6cd2642a1621a3"
g := packr.New(gk, "") g := packr.New(gk, "")
hgr, err := resolver.NewHexGzip(map[string]string{ hgr, err := resolver.NewHexGzip(map[string]string{
"14b27f88168b4f08f9d703f2a9b5027c": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece54efef9eff3fdef04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351ae6f3e9c2e430100c1d450e1e839c44d7df365f3eed6ed6ebdbdde7cbcde6ebfae66a1599e528b8fdbeba4c642f36b50dfbdad2f0a2e3e6e0f1ec6f85b9a8d83d60d418243eb64c41340592eabea8069563ef6da80cdc0d0060acb5ab6db44e30ea84a2b3678cab83fc783f9efc21e3a6b1421cce25bb4320c715ee1c8d07f176c835da466a57a37b30c73a82490cdca98fd7576a02aa9fa0ad3c050513d552d867aa751b59d871b312d7aaede96bf2c80731309ba623a420183bdb18284f30a244c294952380d113aa28bdd860cf5edb5e9ee862befc60727883a1bea0760da9c1cef6953ecfbb3f5afa77f31ebdb3aec6eae5157ce67f335196b3b2347d8437f8405773ce49aca47cf8a526002ab87c2e67cb625a4c8bb27fc8a5ffdbe6ef000000ffff0987409f7d030000", "08a57ee8c539d8871f262cf7a361df41": "1f8b08000000000000ff9c90314bc3401cc5f77c8aff96045c0ae2521c62724a30b994f46ee8943bd3030f1b2bc9298e6eba281d8a1d74d04941280e226a07bf4c9bda6f21676b23bab9dc71efeefddebd7f9a0bae04b4b9e23bbc10b09773d52d92b6c8ba75e3f0b760b831720802e26c040818cf954c3ba2606019004cb619c87d65d56a3650dcf4b730f2004704300d02702889121fbb310a1126e046e1d76e8e5f46b3fed0f7cc15cd5052750483239ea7bb3cb7d656ed8ab0b44c7ae7d3bbc7b9215332130cf45a289e1d54cf3db4e9d080804be3186192103f444de2840d8830d086a78bfcbd5b8694d72793dec5f87d58f65fcbc1f36cf0340f4cff1158fdfcec6a327afb816bc47ee8c42dd8462db0f4046dadea1393c7c9a29cb568691bf6376add2c2f4fa70f371fb7f766ddf80c0000ffff632acdfbc6010000",
"0bf2c3c279f0863ca37680167a1668e2": "1f8b08000000000000ff4ccccf4ac0300c06f073fb14a587a120b3dd86caa02878f5e84d446a1b59b15d679afae7eda53a7497e4fb7e813cdcc6002b3d72e6cb2a8c909833cd6ddc90db4ef470d9ab5ef57ad6e3a82e4ecf5fd1522e4f1e52bea690205732ba7408d6dfffd70f0c0487be592c3fdd1056e86276e62e3b1b3bb7b40b994a2f57e9793a6b5b72661d857710460c8ab3e0638b7a8ffb5b61e4b448cede2ae0d79f093928958ae40c3ec11d78dc99d0ae079e7ef93b0000fffff662d40406010000",
"10621fa6dab19977ebee067a93861c10": "1f8b08000000000000ff84904f6bdc3c10c6cf9a4f31ab9314f695ef6ff0a16942bbb081d2e41eb4f2c82b6c4b4692932d61bf7b99c52d4b5b5af01f31f3cc4ff33cb37583ed093b9b00c234a75c5181902ec54aa72a41483fda9effa9f0b752a921f61240c83ed4e372302e4dcd218c81df66c8b6a6d2cc43dfb8147d33dbd17621ca7fcb577233067794a0015e6dc60e6f78353eba7ac216d7c5cc9d75439fd3123ba501fc121d3e53a98f364435e1cd0a338f1adf41b005f34455b12f2fb7288d698cb95c29f575ff9766d3253750fecfa5694e85cc373b8d3f07bed85c4869105d28f630d23eb823fedf622ae613558aaf4adeef9e3edced1f5ef6bb8f9fa5c64d8b5282081e37d733ef20b84639f338fbe7659659e9db4b71d3620ce34526661b835394b30621cec00f87c332ca3965f8416a718ddeec62a87f405d93568af3c849b2a7e0b1dba2f3db1516e98df3bdb749e9dbbf933255f63199af4b6494f32bf037d32fb8da7d269bbbf476919f41a4621e4ea1aa4c55c319be070000ffffe08efaf7a5020000",
"14b27f88168b4f08f9d703f2a9b5027c": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece5eefcf3dfe7fbeb04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351acaf97cba30390c0843479183c72027d5f5b7cd974fbb9bf5fa76f7f972b3f9babeb95a4566390a6ebfaf2e13d98b4d6dc3beb634bce8b839783cfb5d612e2a760f183506898f2d53104d81a4ba2faa41e5d87b1b2a03770300186bed6a1bad138c3aa1e86c1ae3ea203fde8f277fc8b869ac108773c9ee10c871853b47e341bc1d728db691dad5e81eccb18f60120377eae3f5959a80ea8fd0569e8282896a29ec33d5ba8d2cecb859896bd5f6f43579e48318984dd31152108c9d6d0c942718512261caca11c0e80955945eacb067afadaf5fe062befc60727883a3bea3760da9c1cff69541cfc73f7afaf7f41ebdb3aec6eae5257ce67f73312b676569ca1cdf60035dcd3927b19272f14b4d005470b92e67cb625a4c8bb27fc89dffdbe5ef000000ffff82fe973e7e030000",
"157b33c7997882e0620862106b4b53c7": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b0b03030325b04c49666e6a7e690948d2b058890b100000ffffb7699cdc36000000",
"1769e4a13f3ecbd1dbb3698b5f8cae8a": "1f8b08000000000000ff4ccc41cac2400c05e0f5e414610e5092fefc28822bafe04e5c0c4d16814ea74ca35e5fa22ebacbfb1e2fb7cb6cbaf81dd252aae219b3686d19d2da9bb7c83ead195211e991783c0c34d0c027e691399ac9ed19cb7f826432c7c90449accc57abda1efe1912d52d43ea5a64c7e38f5fdd5c77fef77544c4f8b96b8eb46578070000ffff6f600d93b7000000", "1769e4a13f3ecbd1dbb3698b5f8cae8a": "1f8b08000000000000ff4ccc41cac2400c05e0f5e414610e5092fefc28822bafe04e5c0c4d16814ea74ca35e5fa22ebacbfb1e2fb7cb6cbaf81dd252aae219b3686d19d2da9bb7c83ead195211e991783c0c34d0c027e691399ac9ed19cb7f826432c7c90449accc57abda1efe1912d52d43ea5a64c7e38f5fdd5c77fef77544c4f8b96b8eb46578070000ffff6f600d93b7000000",
"1794b30bcdd9584d5877963a3cb28504": "1f8b08000000000000ff8c535b6b1b3b107e5efd8a3982046d70b4e7e1701e5cfc10dc10426b3790b62fa504453bab08ebb2c8e3c4c6ec7f2f922f4dd2d2e66159edf25de69b19f54a2f9441685564ccfa3e2602c12aae63205c136715ef3c71c62abeddca596c6f1276763d0cdbad9c2b8fc3d0d8409882728d8f2dbacc30961e56f75247dfdc5b67f3d32c92a2b86cfa8569b4d20fd878f4e5f016420c5dd32ba75a1bde0077d1705633d634268e0d064c8a107600a0181d180c5e33daf408775e4349d0298db06555d380d763385fe066b2c0cd452238cfc8894162d534977c91c86a8742c3be4d72ba7b8fc0b659edffff6a1067a51f720f1e01a61453fd7b035cf736e1a4952dfa78593e5875d1b66fb51b814a042f1d6b1098d21f6c59f51e1dd241bf78fd25d333c181b16e1534ccf16936153508afe1ec305439db1f4aec3d2577f75125d09d8125a595a6fca79a3a8b819e71a73174d6b06a6095ed0a7f02fbe9cb2b24c18f488adef15a7e095ea5e583729f3fcd3e8a53dd99fa5de1fd3381605d714948ab148aa8d73001388accf149e8cec85d1d353b400f01450b67ad8a35dcd8606653a169fdba472f3a93ed8e75b7d26b798b945923383d9a5e13faed07dc8c81f736183e82afcaad700cdfbedf6f0805ef6330bc1e41590645368631fc3bfc9acb45232fb3afc8773614af9bebf955bdab469c3cd6bc0ca12ed95f65db2d82f839e125251b4c56de21a1f3246ffb64037582ab4477272dcf2b9117e047000000ffffe48ced133d040000", "1794b30bcdd9584d5877963a3cb28504": "1f8b08000000000000ff8c544d6bdb40103d6b7fc57421613738520fa507171f821b4268ed06d2f6524ad8ac469bc5fb21d6e3c4c6e8bf97956ce7a325cd416825cd7b6fe6cd43add20b65106a1519b3be8d8940b082eb1808d7c459c11b4f9cb1826fb7e52cd657091bbbeebaedb69c2b8f5d57d940988272958f35ba8c3096ee56b7a58ebebab5cee6ab5a24457159b50b5369a5efb0f2e8fbc35b00313455ab9caa6d7843b98b8633c9585599383618302942180a806274603078cd68d322dc780dfd048dd2085b565415783d86d3056e260bdc9c2582d35c393148ac98e696cf1259ed5068d8d9544e87fb086c9dd93e7e90204e7a3fca5df10830a598e4bf0570ddda8493baacd1c7f3fe81156775fd56b911a844f05c5182c0945e9165c56774487bfe5eeb3f333d21ec186b5641c31c1f66532141780d27fba596b3dd6104ba815c2764efc00e9d8dbe572947add08d81036e1a43634d7e4bb0db78f9fddbec2b2b242b6cd3534c0e5f2e90043f60297ac765f92378959677ca89634df2530f793781605d562d12d22a0556744ff8340d54536731d0538eac2d8e75635e25f21a26f038c41c1f060c2b740393ddfcb0f5ba9cbab844213bb687ef6d14359cd42a4ab8b2c1cca642d3fae5269ef99f5b38f45f975e97d748193582e3432397847efb053763e0ad0d868fe0a7722b1cc3afdfb71b42c1db180c9723e823a7c8c63086f7dddfb3ba68caf3ac2bf29f21f45a5797f30b3974238eee25eff72b7b3f5ecc36c44d3ce66849c9069399874a683c95d76db2811ac155a29ba39ae7e0e598fd090000ffff9a984c0da3040000",
"225361cfe91f8a3ee02db98f64637aa4": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece54efef9eff3fdef04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351ae6f3e9c2e430100c1d450e1e839c44d7df365f3eed6ed6ebdbdde7cbcde6ebfae66a1599e528b8fdbeba4c642f36b50dfbdad2f0a2e3e6e0f1ec6f85b9a8d83d60d418243eb64c41340592eabea8069563ef6da80cdc0d0060acb5ab6db44e30ea84a2b3678cab83fc783f9efc21e3a6b1421cce25bb4320c715ee1c8d07f176c835da466a57a37b30c73a82490cdca98fd7576a02aa9fa0ad3c050513d552d867aa751b59d871b312d7aaede96bf2c80731309ba623a420183bdb18284f30a244c294952380d113aa28bdd860cf5edb5e9ee862befc60727883a1bea0760da9c1cef6953ecfbb3f5afa77f31ebdb3aec6eae5157ce67f335196b3b2347d8437f8405773ce49aca47cf8a526002ab87c2e67cb625a4c8bb27fc8a5ffdbe6ef000000ffff0987409f7d030000", "191590fe9aea37da87e1139609a72c5b": "1f8b08000000000000ff4ccc41ca02310c05e075738ad2030c497f7e14c1955770272eca248bc0743a74a25e5fa22ebacbfb1e2fb7cba2b2da1dc25aaac4734c2cb525085b6fd63cdbbc250885b97ba27c9870c2894e99329137b3e9d397ff084179f19310026b59ae5aa53dec3344ac7b82d0a5f0c0f9c7afae2683ff7d3dc618fde7d01c714ff00e0000ffff7dc54fc8b7000000",
"213aa9a2a3ab9063ff31669f2b262397": "1f8b08000000000000ff248eb16eeb300c45e7f02b2e3249ef05d6de31f5da0e457e80b61959b52d1a120d0f45ffbdb03391e0bd073c21e07fb7a579c09e8aa4fc2dbd5108788c82d7dd3862e1492aea5604360aaa6d1d5245563b4b8694cfe09932cf2fae215ab99f380a0656a2b4ac5a0c8e2ed7986cdcbaa6d72544d5384b387e5fc9138510f52d4a96c226980a9b5698ea7cead173cb3db2ec0fa9d6b23a0ff76f60bde1089cbf414ad1e2f143979573eadd4135f7c3c765d9dba3fa297b7b3fc7970ca99edbc7bbf7f44b7f010000ffff3c96d9e80d010000",
"225361cfe91f8a3ee02db98f64637aa4": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece5eefcf3dfe7fbeb04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351acaf97cba30390c0843479183c72027d5f5b7cd974fbb9bf5fa76f7f972b3f9babeb95a4566390a6ebfaf2e13d98b4d6dc3beb634bce8b839783cfb5d612e2a760f183506898f2d53104d81a4ba2faa41e5d87b1b2a03770300186bed6a1bad138c3aa1e86c1ae3ea203fde8f277fc8b869ac108773c9ee10c871853b47e341bc1d728db691dad5e81eccb18f60120377eae3f5959a80ea8fd0569e8282896a29ec33d5ba8d2cecb859896bd5f6f43579e48318984dd31152108c9d6d0c942718512261caca11c0e80955945eacb067afadaf5fe062befc60727883a3bea3760da9c1cff69541cfc73f7afaf7f41ebdb3aec6eae5257ce67f73312b676569ca1cdf60035dcd3927b19272f14b4d005470b92e67cb625a4c8bb27fc89dffdbe5ef000000ffff82fe973e7e030000",
"236ab314cd41c9b7b2c5194c0eb72bb1": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000", "236ab314cd41c9b7b2c5194c0eb72bb1": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000",
"2f762fe51f2becdb8677b17926a52f03": "1f8b08000000000000ff8491c1cbd43010c5cf99bf622c28ed529a837859e96115bdf921ace0395f3a5f366c9b84e9b4bb52fabf4bda5541040f43cbe3cdcbef31c9d8ab71849d07f0438a2c58822a6c0c4277294015e2072a0054b12ccd97d87d657af1f7755d96e6c90cb4aeda07210ea6d723f1eced6e765e2ed37363e3a09f7deff3e82b1b89a34e57a7fbe88affbb0289e664f5cd7047a1800a406b178f8e02b111c2dd8b12638f37cf04f223119e52c25178b2820ba871b67878a035e7fd0bca71b278d88337951856809729587ca2db29a5f25f8b35babfb62a2c4d4a7838a554a3ede3489f73460e2aab1a89394fe46a01958d2dbe39a5b480ca60471c675b83da708ee86a502ba83f29ed2327f75056ee355a132cf5786cf171a2e6bb97cb373f509ca4fca57d30f6ea384ea1cb0c6fdf1df2119b33d918ba0a94f22f1bd8b145d79c2f9374f1164a2bf7eafda6bf6a31f87e7b54f5d1359f7281b2c890679e7f6fecc5cad773556c4573f2ba176b3ee60e655676e2fcbb8262928903acf0330000ffff2075693478020000", "29d20d6ca71bd38c525aa7a6728b3c5d": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a44b3a1dc7332198e4be4b118127b7f73fc438dfad687df96fb812425396bd7d9ab9eeb19f6e2dae84df000000ffffd60a1b01ab000000",
"33550cc0d0a7c442ee2f7ef103747430": "1f8b08000000000000ff9452df4b1b4b147e76fe8ac3be9880d9c57bdf12f270f10a5eb8b4c1daa752c2989c8c5b7777c699c9d2100236166c8b6d6c11c51f0fb6d8e24bb550b0582bfe31c926f1bf28b3d93585ea43e7e5ccccf9bef39df3cd380e44277bbdf397d7efcf07fb27f04fe93f18ec3d0721b9e6d0df5eef5d9c41d439ed5d7c8c3637fa3b67fd4e6778f505d87c6906a2771b30b7b050322ce23823d262bd96f0a24e7bb8ba963719c8c192d642e51da78a217a5ca05436e39c796857b8efc4d40af7728bf55a0da572886a049a3e85225871ee6fab4088eb0b2e3558ccd54bf5c598c838e34e2a1c9fe243bcb3e3ad5518f362c1311c7da11b77a1a8701d1a045c53edf240ddc0e2496965993284e8ed65b4f9ba777935d83a862615c2adb6ec668852b93c681927fbdbe7d18fce142477105d7e883eb5219c9e82f02fb06d9296aaa2cf6d8532742b6887d3239d7bf71766f3d03f588d36df0c4fbf452f0eaf778f8657bbbdeffbfd9dc3c1d6b151f87a7cbdfe0a32ddf641aedb3ec8769f1d75d73e03215c98c681f172aa51048b0ad72aa4a9cc8d5f7612cb0cb546a9cad4f3b250841af5141608491a837fd1e7d02400005254a0e4060c32e943a6bedab3c6d72c48d47519a83b010532618a3ca08d39f43c0e9938cce3ca1f531fceff7f1b39b952229bf46cd678f6b83015ae6dfea699760c328ba1ce5bceb2a49aab9c791e47d14679c9d4b46e80ad0249428b101f95323ea7ad40934c282d8d4901f58dffd3f0e817d37d2e5153a6b2c5c91a977ede32280b42eab955aa316f495ca9bb12abd6e4e3db0494485a4e446678a031d0bfe93c513cd0949911272b23cca8e0cf000000ffff54d4b889ff030000", "2f762fe51f2becdb8677b17926a52f03": "1f8b08000000000000ff849141cbdb3c1084cfda5fb19fe12b7630d6a1f492e2430aedad2f85147ad62b6f14115b12ebb59362fcdf8becb48552e861112c33a367d864eccd38c2ce03f82145162c41153606a18714a00af1031500aa5896e673ecbe305dfc635d97a5793103adabf6418883e9f5483c7bbb8b9d97ebf4dad838e857dffb3cfac646e2a8d3cde93ebae2dfaa40a239597d37dc5128a002d0dac5a3a3406c8470d7a2c4d8e3dd33817c4f84a79470149eace0026a9c2d1e9e68cd797f41394e160f7bf0b6258615e032058b2f743fa554fecd58a3fbc355616952c2c329a51a6d1f47fa9433725059d548cc7922570ba82c6cf1cd29a50554063be238db1ad486734457835a41fd4e699f39b987b2f2a8d19a60a9c7638bcf1335dfbc5cbffa81e224e5cfdd07636f8ee314baccf0f6dd211fb139938da1ab40297fd9c08e2dbae67c9da48bf7505a7954efb7fd7f2d06df6f9faa3ebae6632e501619f2ccf32fc75eacfc7fae8aad684e5e33e8c658565b19269938c00a3f020000ffff41730b5c6a020000",
"33550cc0d0a7c442ee2f7ef103747430": "1f8b08000000000000ff94924f4b5b4d14c6f7f3290e7763027a2fbeef2ec145b18285d2066b57a584313919a7bdf7ce3833090d12b0b1605b6c638b28fe59d8628b9b6aa160b156fc30c94de2b72833c955a1bae8269999f33ce737e7991b04901c6e774ede5c7c3ae9ed1cc29dc23de86dbf02a98411d0dd58e99c1e43d23aea9c7e49d656bb9bc7dd56ab7ffe1dd84c6112928fab303d3b5bb02e120403d35cb532f425ad667f6939672b3006f3c6489d0b8232d630141295f699102c44bf24a2c0594b221c9bab562aa87440743d36f4054c80e76aff7b794278248532e0316ee6ab73cec80413410a763bb7712bdf2dbdfc95cf01afe4184953bf4d45250f681c0b430d17b1be94b94969e9396508c987b364ed5de7ecbcb77e008b544a5e6ef88b35549a8bb86193ec6e9c24bf5ba3303c83e4ec73f2b509b5f151a8fd07be4fd256658c84af51d57809fddaf880f3e0e1ec540ebabb4bc9dafbfed1cfe4f5dec5d67eff7cabf36ba7bbb9d75b3fb0841f07172b6f21d36eee8eb59bbbd9f6cbfdf6f2374284b4f706268a2962023c2ab9974f4b99cbb8fce17f91a131a8749186611626a042438d794286f782bb18095824004a96a0c06396491f31cdd49fb2996641a1a9aa58c36d82fcb0c9235a9fc6301419f73b830bff6e7d3c73ff26f7f048cbacbb31c0d5d4ae2b95dcb71fa59d732000606872e005f62d024debc579dbc373c586c536f2a44148845adb3c53a8b36ba378cc20a6910d7a1c9e5c4b37120a0d65daa2462a424539cfea3ca8d19097a9c19ca770a1ca1596bd91a73731b4bc0e9914b1c1d8fcc579a6456c287398d2403368f7270000ffff07b2c244e7030000",
"336d416ed5faa95a29de7b6afd385568": "1f8b08000000000000ff9452418bdb3c103d6b7ec57c860f2c486d7a0dcda194b69bc386b449ce65228f9d21b2642499ee62fcdf8b9c65d9c01eda838d34f39edf9b371ec85ca963ec491c80f4830f094b50456ba92b40153edede7594ce91cd97f81c0dd9e598a4e7024015d3543dfa661fb895a7799ea66a473dcf732d2e717064eb4632be937419cf95f17d7d162bf9a9af81928ff570ed6ae35d5b0f64a911f71770ebbb0234403b3ab34c506a9c4065ebd59e42e45283b2beabb64e52e9c46aac6b6cf83c7698416bcccd46c2661a285d66500db71c96ea17ebdff25b5f16af53614c1452a141bd78bd096850bf566832f1dbe8cc0a39045c6fb091a5ff79183244daa5fedf069dd86c570de4c4941c820635833299d3d3954b7321873e568725fa157ed4a06e6ba8763e49fb5c9a15be6ca33a6cbf3f9cf677f71fa7edf1ae70fcfaf3f1aeb0dd1d35a8d687c548ccca9f3e18506fa6ee3821e14d16ff8fc50a637548415c576a9d49bf25990bc6e50b8622ffb3833528a55e63cb19a97753e7275942572aff76d5c1320fe5edc8c6bb6669054e6370ef587938edb350c32d8d36adefb0730e7e863f010000ffffe9e8e3430d030000", "336d416ed5faa95a29de7b6afd385568": "1f8b08000000000000ff9452418bdb3c103d6b7ec57c860f2c486d7a0dcda194b69bc386b449ce65228f9d21b2642499ee62fcdf8b9c65d9c01eda838d34f39edf9b371ec85ca963ec491c80f4830f094b50456ba92b40153edede7594ce91cd97f81c0dd9e598a4e7024015d3543dfa661fb895a7799ea66a473dcf732d2e717064eb4632be937419cf95f17d7d162bf9a9af81928ff570ed6ae35d5b0f64a911f71770ebbb0234403b3ab34c506a9c4065ebd59e42e45283b2beabb64e52e9c46aac6b6cf83c7698416bcccd46c2661a285d66500db71c96ea17ebdff25b5f16af53614c1452a141bd78bd096850bf566832f1dbe8cc0a39045c6fb091a5ff79183244daa5fedf069dd86c570de4c4941c820635833299d3d3954b7321873e568725fa157ed4a06e6ba8763e49fb5c9a15be6ca33a6cbf3f9cf677f71fa7edf1ae70fcfaf3f1aeb0dd1d35a8d687c548ccca9f3e18506fa6ee3821e14d16ff8fc50a637548415c576a9d49bf25990bc6e50b8622ffb3833528a55e63cb19a97753e7275942572aff76d5c1320fe5edc8c6bb6669054e6370ef587938edb350c32d8d36adefb0730e7e863f010000ffffe9e8e3430d030000",
"348f254eb8f48eaf3d0330c83c18324c": "1f8b08000000000000ff9451c18ea3300c3de3afb038255d44be600fedf6b28756d5767f2010173c85240aa18c84f8f711d0a9462355ea9c78f8bd3cdbcf4ae1afa2e7c6e0c081d8be51194129fc5f13aef5a82b6cf5953aecfa40186bc22ef6057287d6c5451491ed425cd8ea667d9703785d5e75456818805bef424401892f301dc7fce0cc29d085dfa7691cf3a36e699a94f69c42f294661b2958dd28a3dd4bba8ec28d82aa822f7fa2af63f42febb9a41420492b8e755fe4a56b55e55cd5909a134d4102dc7440a3dd29b81b1b0af87b093b3fd270a6288c7633ccf00ef6bb07fc4786bbc7dfe18f5cacee5d9fd8ddd9d57221766c8db034085fe47b6add79d9526638d7369ffaf3fa9552025c7a5be25fcb71ebbd9028365bef339cab42664821b8207184c46bcba5589bcc47175fb6ccbecf99e19ceb3ad77c91151d69d87a2f254cf0110000ffffb4884e698c020000", "348f254eb8f48eaf3d0330c83c18324c": "1f8b08000000000000ff9490b16eeb300c45e7f02b084ff67b86b4774bb70e0d32f407149991d9d8a240d34901c3ff5e38e9d031dd84ab7301dee33dfe3fcd3c74786325ce9f140dbcc78f9ef0915b4838860b4d38cd4a683de164f30979c22c76870c39df3fce9cc3f0e8398012e22524c28e01782ca28635ecaa6571efd21d95cefcb5aecbe20e61a475f59c8d3487c17741aa67b889f4ca919e66497dd212ffc2f766a502d85589ad9f4f2ecae893481ac86fbe2a6800bc4ff29228930623bc683099d0ee3ee13ce7886f996d5f4add60fd6f5f4a8b5b5a372d92aa68830bec4ac81cebade25e377b7517c41d55aedc91b6f8b3f457b21de60e746b719bf4781de8b62fa5696085ef000000ffffe36b7bafd7010000",
"359dcf82ea381d6901e53f88ff235896": "1f8b08000000000000ff9452df4b1b4b147e76fe8ac3be9880d9c57bdf12f270f10a5eb8b4c1daa752c2989c8c5b7777c699c9d2100236166c8b6d6c11c51f0fb6d8e24bb550b0582bfe31c926f1bf28b3d93585ea43e7e5ccccf9bef39df3cd380e44277bbdf397d7efcf07fb27f04fe93f18ec3d0721b9e6d0df5eef5d9c41d439ed5d7c8c3637fa3b67fd4e6778f505d87c6906a2771b30b7b050322ce23823d262bd96f0a24e7bb8ba963719c8c192d642e51da78a217a5ca05436e39c796857b8efc4d40af7728bf55a0da572886a049a3e85225871ee6fab4088eb0b2e3558ccd54bf5c598c838e34e2a1c9fe243bcb3e3ad5518f362c1311c7da11b77a1a8701d1a045c53edf240ddc0e2496965993284e8ed65b4f9ba777935d83a862615c2adb6ec668852b93c681927fbdbe7d18fce142477105d7e883eb5219c9e82f02fb06d9296aaa2cf6d8532742b6887d3239d7bf71766f3d03f588d36df0c4fbf452f0eaf778f8657bbbdeffbfd9dc3c1d6b151f87a7cbdfe0a32ddf641aedb3ec8769f1d75d73e03215c98c681f172aa51048b0ad72aa4a9cc8d5f7612cb0cb546a9cad4f3b250841af5141608491a837fd1e7d02400005254a0e4060c32e943a6bedab3c6d72c48d47519a83b010532618a3ca08d39f43c0e9938cce3ca1f531fceff7f1b39b952229bf46cd678f6b83015ae6dfea699760c328ba1ce5bceb2a49aab9c791e47d14679c9d4b46e80ad0249428b101f95323ea7ad40934c282d8d4901f58dffd3f0e817d37d2e5153a6b2c5c91a977ede32280b42eab955aa316f495ca9bb12abd6e4e3db0494485a4e446678a031d0bfe93c513cd0949911272b23cca8e0cf000000ffff54d4b889ff030000", "359dcf82ea381d6901e53f88ff235896": "1f8b08000000000000ff94924d4b1b411cc6effb29feecc504cc2eb6b7040fc50a164a1bac3d9512c6e49f71eaeece3833591a246063c1b6d8c616517c39d8628b976aa160b156fc30c926f15b94996455a81e7a49e6e5799edfcc33ebfb901c6e774ede5e7c3ee9ed1cc2bde203e86dbf0621b9e6d0dd58e99c1e43d23aea9c7e4dd656bb9bc7dd56ab7ffe03e8747102924fab30353353342ec7f707a6d95a75e84b5acdfed272deec400ee6b4162aeffb158c31e002a5f228e73440afcc43df5acb3cc8cdd6aa5594ca77543dd2e4258c836bf7eeba05c761a1e052834b999eabcd5a23e594fb29d8ceecc48e3c3b740b573e0bbc92632874fd361511cc2751c435d18c47ea52666f4acaf38422241fcf92b5f79db3f3defa012c122158a5e12dc62815e351c334d9dd3849feb44661b806c9d997e45b13e2b15188ef80e73969540543ee2994312ba3178f0d388f1ecf4ce6a1bbbb94ac7de81ffd4adeec5d6cedf7cfb73abf77ba9b7bbdf50343f87970b1f20e32ede66eaedddccdb65fedb797bf3b0e17e6dc407929458c834b04730be956e6b22e6ff85fa2a8354a552241908571a8924061c17186e782fb1872587400a42843914534933e62daa937693acd82445d939182db048561c813529fc220e019fb3b8d0bff6f7d3afdf026f7704989ac3d31c0d5ad6d2a11cc331fa5b9e740004051e7c1f5e725d15ce5cc93f88ad44b7326cab59a86a1370a4ec3714254cad49ab26d8ad292451422129abec7e0d9b592432e5113aa0c71a4ca6598778dce859804ac4234e65d890b3526b1e28e3cbf89a1c475c8048f3446fa1fce0bc5234da8c594079a41dcdf000000ffff1ddc747cee030000",
"39a955dfabc5df68502b59574724045e": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000", "39a955dfabc5df68502b59574724045e": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000",
"3e325e6ab86420d1ae1f36242db87f0e": "1f8b08000000000000ff9c90314bc3401cc5f77c8aff96045c0ae2521c62724a30b994f46ee8943bd3030f1b2bc9298e6eba281d8a1d74d04941280e226a07bf4c9bda6f21676b23bab9dc71efeefddebd7f9a0bae04b4b9e23bbc10b09773d52d92b6c8ba75e3f0b760b831720802e26c040818cf954c3ba2606019004cb619c87d65d56a3650dcf4b730f2004704300d02702889121fbb310a1126e046e1d76e8e5f46b3fed0f7cc15cd5052750483239ea7bb3cb7d656ed8ab0b44c7ae7d3bbc7b9215332130cf45a289e1d54cf3db4e9d080804be3186192103f444de2840d8830d086a78bfcbd5b8694d72793dec5f87d58f65fcbc1f36cf0340f4cff1158fdfcec6a327afb816bc47ee8c42dd8462db0f4046dadea1393c7c9a29cb568691bf6376add2c2f4fa70f371fb7f766ddf80c0000ffff632acdfbc6010000",
"40aa45750f8397d706e3d8fdd82fa11f": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a4cbe9389e09c124f7598a083cb9bdff21c6f96e45ebcb7fbb95109ab2ecedd3cc758ffd746b7125fc060000ffffe2756aadaa000000", "40aa45750f8397d706e3d8fdd82fa11f": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a4cbe9389e09c124f7598a083cb9bdff21c6f96e45ebcb7fbb95109ab2ecedd3cc758ffd746b7125fc060000ffffe2756aadaa000000",
"43befbfad04c8efdf57be993ceb9e432": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b4b03030325b04c49666e6a7e690948d2b058890b100000ffffb9f9177936000000", "43befbfad04c8efdf57be993ceb9e432": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b4b03030325b04c49666e6a7e690948d2b058890b100000ffffb9f9177936000000",
"46713bf4406bd2896c32e5778efb1eb5": "1f8b08000000000000ff8c53516e133110fdb64f31b144e54591f7bf281fd0464140d3aa69c527f23ab3bb56bcf6e2f5a691a21c831b803800df1ca79c03d9bb698b2a041f96ecf1cc7bf39ec7ad541b5921d421b494eaa6753e00a784590c790c324a495b00dbefc5855b5f792cf5ee70d8efc552367838e4b2d58c92bf5e6b1bd05b69f2c6add1c4cc4a87ba2f84724d5e68a3e3ca375e06d7e5eda6ca95b365de4a23d7dafe47ba7115a3a468e05f89473d7961e41a1bd905f48c66946ea5876eaba02dc439366e857e8b9ed23c8725de81c53b905034d0a5b8a0656f55bce1dd9f151970b495b6082f8b46ccd3760ae87d5cce67b0a72452714a48ada00bbe57210609190052ddb03d73b6d41525e4404946892e13ce0c465bc4020367518c08ae312c13b7b691beaba5b9b9bcf8c04f6a95bd4a259319586d12cb08327944997bbf7461bed3ddd887c7d07b3bd09281d16a43e3311a34838e9251e30c8a469c63297b13869e79adc6eeb33830e21a2b1d3d8e0ebdb9187370b4a58baaac0ed7ae0f0fe18c8ea4c351ac82f48167f4d8d7810ee63f2d7c62767218c595b6156fb5ad324a2a389d018a85777dcb59fe30952ca3242aaec4627ec359de45263685daddddb8449b45d547c288c655d825b2336703ee4262d3257c1adef874166768205761378dc63d7f03e3aae8baf39c45cc6132f88b6dc6124a46095161275e17ce878f3ad4ab2043dff1f4d2c33efaa815de5ab995dac8c2e0b1d33c07dcc9a63508a5f3e93f83c7cf3d76016a69d7e661781f5572f54cd2264a39499f55bc4fbf2736fe168d71a7c016ce485bc1fdd7efbf7e7cb9fff6132693099ba60951e2ddea72c93783747af81d0000ffffb720960459040000", "46713bf4406bd2896c32e5778efb1eb5": "1f8b08000000000000ff8c534b6edb30105d8ba7181368401506b94fe1459b042edae68338419705258f64c214a9529463c0f0317a83163d40d73d4e7a8e6228db7511f4b310407186efcd7b7c6c75b9d435c222c69631d3b43e44102ce30ea3a24dce58d616c0371b79e9e737012bb3de6e371b79a51bdc6e956e0d67d91fcbc6450c4e5bd5f8395aeaac4d5cf4852c7da30a630d7d6a1974f49d6a97b52abdab54abad9e1bf71fedd6d79c654503ff6adceb5185d5736c741731709633b6d201ba55096d21cfb1f1330c2b0c8c290557f8000e1f4043d14097f625ab7a57524574bf9fc841a0ab8d43785e34f2222dc78021d0e7430e1b9611956059565635148d1c0e9e7957999a7623ec74cbbbebcb772ccb5966aa04313954a61805271d32fac6f25cdebb46876ea1ad382963fe22b58f26e08c25c62c60ec8363d9f608ab8c03ccc07f8c41bce2a4aceabf02915b13e858b6133c2131e758e9dec60173c0a0e0c85bac0d794d4ebdbadc9571674f47129d89b7be8f87ed9c65c39cc3af9c451da2c8d97e842d1b2ee1f8e091e9c9699437c6d5a2358ec6a8e1740228a7c1f7ade0ea904e9eb38cb4d5727a7127b8ea88898f61e11fee7ca2cd49f09e90d04419d789ecccbb88eb98d84c051f86bb3e9d509606f232aec764df532fadafe505a54270c21c12229ead729e50f21486b57c59f810df9bb898451dfb4ea46b1fd6e4a329f1dee99536561716f7932a05b8d64d6b112a1fd2bb86801f7bec222cb49bdb43887fa914e513494b9272921ead7c9b5e110dfe1aadf5a7c0a7de6a57c3e3e7af3fbe7d7afcf21d46a3111fa77094f2cdecfa4a2c07e96cfb330000ffffca8ab99f61040000",
"468e50d126ac1e7c1a9ea44dde207990": "1f8b08000000000000ff8c53516e133110fdb64f31b144e54591f7bf281fd0464140d3aa69c527f23ab3bb56bcf6e2f5a691a21c831b803800df1ca79c03d9bb698b2a041f96ecf1cc7bf39ec7ad541b5921d421b494eaa6753e00a784590c790c324a495b00dbefc5855b5f792cf5ee70d8efc552367838e4b2d58c92bf5e6b1bd05b69f2c6add1c4cc4a87ba2f84724d5e68a3e3ca375e06d7e5eda6ca95b365de4a23d7dafe47ba7115a3a468e05f89473d7961e41a1bd905f48c66946ea5876eaba02dc439366e857e8b9ed23c8725de81c53b905034d0a5b8a0656f55bce1dd9f151970b495b6082f8b46ccd3760ae87d5cce67b0a72452714a48ada00bbe57210609190052ddb03d73b6d41525e4404946892e13ce0c465bc4020367518c08ae312c13b7b691beaba5b9b9bcf8c04f6a95bd4a259319586d12cb08327944997bbf7461bed3ddd887c7d07b3bd09281d16a43e3311a34838e9251e30c8a469c63297b13869e79adc6eeb33830e21a2b1d3d8e0ebdb9187370b4a58baaac0ed7ae0f0fe18c8ea4c351ac82f48167f4d8d7810ee63f2d7c62767218c595b6156fb5ad324a2a389d018a85777dcb59fe30952ca3242aaec4627ec359de45263685daddddb8449b45d547c288c655d825b2336703ee4262d3257c1adef874166768205761378dc63d7f03e3aae8baf39c45cc6132f88b6dc6124a46095161275e17ce878f3ad4ab2043dff1f4d2c33efaa815de5ab995dac8c2e0b1d33c07dcc9a63508a5f3e93f83c7cf3d76016a69d7e661781f5572f54cd2264a39499f55bc4fbf2736fe168d71a7c016ce485bc1fdd7efbf7e7cb9fff6132693099ba60951e2ddea72c93783747af81d0000ffffb720960459040000", "468e50d126ac1e7c1a9ea44dde207990": "1f8b08000000000000ff8c534b6edb30105d8ba7181368401506b94fe1459b042edae68338419705258f64c214a9529463c0f0317a83163d40d73d4e7a8e6228db7511f4b310407186efcd7b7c6c75b9d435c222c69631d3b43e44102ce30ea3a24dce58d616c0371b79e9e737012bb3de6e371b79a51bdc6e956e0d67d91fcbc6450c4e5bd5f8395aeaac4d5cf4852c7da30a630d7d6a1974f49d6a97b52abdab54abad9e1bf71fedd6d79c654503ff6adceb5185d5736c741731709633b6d201ba55096d21cfb1f1330c2b0c8c290557f8000e1f4043d14097f625ab7a57524574bf9fc841a0ab8d43785e34f2222dc78021d0e7430e1b9611956059565635148d1c0e9e7957999a7623ec74cbbbebcb772ccb5966aa04313954a61805271d32fac6f25cdebb46876ea1ad382963fe22b58f26e08c25c62c60ec8363d9f608ab8c03ccc07f8c41bce2a4aceabf02915b13e858b6133c2131e758e9dec60173c0a0e0c85bac0d794d4ebdbadc9571674f47129d89b7be8f87ed9c65c39cc3af9c451da2c8d97e842d1b2ee1f8e091e9c9699437c6d5a2358ec6a8e1740228a7c1f7ade0ea904e9eb38cb4d5727a7127b8ea88898f61e11fee7ca2cd49f09e90d04419d789ecccbb88eb98d84c051f86bb3e9d509606f232aec764df532fadafe505a54270c21c12229ead729e50f21486b57c59f810df9bb898451dfb4ea46b1fd6e4a329f1dee99536561716f7932a05b8d64d6b112a1fd2bb86801f7bec222cb49bdb43887fa914e513494b9272921ead7c9b5e110dfe1aadf5a7c0a7de6a57c3e3e7af3fbe7d7afcf21d46a3111fa77094f2cdecfa4a2c07e96cfb330000ffffca8ab99f61040000",
"470fd5cab5c7a57cec62609827d2c84f": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b4b03030325b04c49666e6a7e690948d2b058890b100000ffffb9f9177936000000", "470fd5cab5c7a57cec62609827d2c84f": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b4b03030325b04c49666e6a7e690948d2b058890b100000ffffb9f9177936000000",
"473893d607815c5c27cec94e0e78e437": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000", "473893d607815c5c27cec94e0e78e437": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000",
"48e53a59007a8dda61d904d989943a09": "1f8b08000000000000ff5ccdc14ec3300cc6f1f3fc143ec2614e9c32525e827748db6022927964c98434f5dd51e15238f862fdfefa8a2e3d47bcdfe93594b8ae00a2c8c40ea0c6cf9e6ac407404494d4defb44b31633a59cb6331f3534bd6209d7162b1c764454d45caa369dfa1bde981cf13f90c359fe90811c1c7effa455cc9739c786374b96ecd1597eb1cf6ee4f1343c9d8e4be0c1cf7ef4bcf82d52c99176add4cbfc33ebc8c2237c070000ffff34bdd5b6e6000000", "47fecc198864e8c30abf93f8cf34c7cf": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a44b3a1dc7332198e4be4b118127b7f73fc438dfad687df96fb812425396bd7d9ab9eeb19f6e2dae84df000000ffffd60a1b01ab000000",
"48e53a59007a8dda61d904d989943a09": "1f8b08000000000000ff5ccd414e03310c85e1353e8597b0a81327940c97e00e9999602292baa4498554f5eea88505edc22b7fbf5ed5759484a713bdc59ace67005164620fd0d2d7c82de12320224aee1f63a645ab9973c997339f2d763d608d879edabd121535fba65de7f18e4726477c310f37a6c49ddc284fee575d5fa44dccb7d9a58e474b96ecc6597eb52f6ee269eb9fb79b35b20f4b9802afe1af532989fee5d2f6cb75df918527809f000000ffff3ae05435f3000000",
"49d0cdb7406397b8e77616d290bcd94f": "1f8b08000000000000ff5492b18ed4301086ebcc530c96901294b5fb95b65836cd35b72be005bc5ec7589b782c674240e80a3a4a0a7a90780c5e0771af81622f3a5d916226ffffcdf8b7a33657ed2ceae8c18f9112630d953014d87e640195e847160095709edfcf67696854673ff8f553d7a4992615af4e05cb2a45a3169d2e361407911bac7434e8e02425a75c8a464003a014ee63bceb5082a130f1addaa17877ec8e5bdc771dee4f27bceb4416dfdbe530781b18835d70c5a0c935f473304fbf6bd33b7c557690a575a0d07bd722459e504ab99a65e7f5708cec2934587776a4a26dd1a644a9c1cf50153e6e7778c33d1b527852ca062a63b26f951653c6d7b70ce56b6dae2ed11c2e75d3623fb27c1b930fdcd7e2e227431f6cfab455ea627b3d0fac5e4ea22d71340d54becfe8173b0c7e58d7aa92e53985b5cc53a17a80ffbd7bbb3c9da536a66957193ce4081fbffff8fbf51bba37a703fef9fdebf1e71750cad1d6d96093668be5329189068c89980c6e3639eacde63cae2f44e636fc0b0000ffff940f602534020000", "49d0cdb7406397b8e77616d290bcd94f": "1f8b08000000000000ff5492b18ed4301086ebcc530c96901294b5fb95b65836cd35b72be005bc5ec7589b782c674240e80a3a4a0a7a90780c5e0771af81622f3a5d916226ffffcdf8b7a33657ed2ceae8c18f9112630d953014d87e640195e847160095709edfcf67696854673ff8f553d7a4992615af4e05cb2a45a3169d2e361407911bac7434e8e02425a75c8a464003a014ee63bceb5082a130f1addaa17877ec8e5bdc771dee4f27bceb4416dfdbe530781b18835d70c5a0c935f473304fbf6bd33b7c557690a575a0d07bd722459e504ab99a65e7f5708cec2934587776a4a26dd1a644a9c1cf50153e6e7778c33d1b527852ca062a63b26f951653c6d7b70ce56b6dae2ed11c2e75d3623fb27c1b930fdcd7e2e227431f6cfab455ea627b3d0fac5e4ea22d71340d54becfe8173b0c7e58d7aa92e53985b5cc53a17a80ffbd7bbb3c9da536a66957193ce4081fbffff8fbf51bba37a703fef9fdebf1e71750cad1d6d96093668be5329189068c89980c6e3639eacde63cae2f44e636fc0b0000ffff940f602534020000",
"4ad10871b856157d685556dee22622df": "1f8b08000000000000ff84904f6bdc3c10c6cf9a4f31ab9314f695ef6ff0a16942bbb081d2e41eb4f2c82b6c4b4692932d61bf7b99c52d4b5b5af01f31f3cc4ff33cb37583ed093b9b00c234a75c5181902ec54aa72a41483fda9effa9f0b752a921f61240c83ed4e372302e4dcd218c81df66c8b6a6d2cc43dfb8147d33dbd17621ca7fcb577233067794a0015e6dc60e6f78353eba7ac216d7c5cc9d75439fd3123ba501fc121d3e53a98f364435e1cd0a338f1adf41b005f34455b12f2fb7288d698cb95c29f575ff9766d3253750fecfa5694e85cc373b8d3f07bed85c4869105d28f630d23eb823fedf622ae613558aaf4adeef9e3edced1f5ef6bb8f9fa5c64d8b5282081e37d733ef20b84639f338fbe7659659e9db4b71d3620ce34526661b835394b30621cec00f87c332ca3965f8416a718ddeec62a87f405d93568af3c849b2a7e0b1dba2f3db1516e98df3bdb749e9dbbf933255f63199af4b6494f32bf037d32fb8da7d269bbbf476919f41a4621e4ea1aa4c55c319be070000ffffe08efaf7a5020000",
"4ee76ca4d3f34ada842b90d87762fe26": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000", "4ee76ca4d3f34ada842b90d87762fe26": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000",
"518b74b34be782fd3abced06105dfdf1": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000", "518b74b34be782fd3abced06105dfdf1": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000",
"532d363951d4f0d0c18e620c67cb7b40": "1f8b08000000000000ff94924d8fdb2c1485d7f02bae2cbd919d3782fd48594d2b75914ca34c475d5f63eca0606030ee24b2fcdf2bfc91499ba61f0bb004c7f79c877b1d8a2356121ae9bf29212955b5b33e404a4922ac09f214124a92b20e09a5c4e590741ddbda62e765a94e7ddf75ec096bd9f71c9d8aca7bd7ca04e90d6a5ea08dba4a85439b33616b9e2bade2e2478fc136dc1d2b2eac29b9438d8532d1f95a5f598da6e2cedb60f3b6e42e9c9d6cb8ac5d382734a39473781e79662e46a3e6fd34f85604e8284101b09c7cd8161d25055a28d0b20f68693fd47a926f60e41be05c0dd014e06568bd61b46c8d8892b4987fcb206d603979ad407a1f97f559346c600d8be9aea384a0780058cc09be7cde6eba7e45498cf100c58a929e9258610db3e62b06714813744e2b814159c382ad75b28286a1c82819934de19ff1fc496a6da1f24e40216b0b31f194fb2a687691a6229c606a3e7b1cbf2bf0f215962e6783642f5f3348bd74fa0ccbe1e1d9c7b8ff4c3b2ad6f1f9d22b5946495907b6f3ca84324d0e43c0ff9a64701926e61ec6cb7e0379fd771c2ffbcdbfa2bc1f36ee1ecbe25a145b38d435e101269004febf708c0dbc856dbdfe3df04e990a5cdcc24182978d6d7d9ce35bdca8fc35a7fca13719a437adbaa04567585c5d777d9ca738d173fd6c4af6a86d23410cfb9fb20dda741cfca1d874407bfa3d0000ffff0c06c20f7a040000", "532d363951d4f0d0c18e620c67cb7b40": "1f8b08000000000000ff94924f6fe32c10c6cff0294696de08f25a70af94cbb62beda1cd46cd567b2678eca0da40314e1a59feee2b1cbbcdb6dbfd7300cbc3c3ccf363c62bfda82a8416c3c168a4d434de85088c924c3b1bf1396694646513334a89df41d6f7e2ce159b80a5791e86be176bd5e03048e54d527e746c6cc460552d0be592ae3271dfed84768ddc99daa4251f838aae95feb192dad9527a55abc2d854f9525fb95ad94afae0a2db75a5f4f1e4b195d8f878cade4a5d55a33c9a8019e5941e54804d700753608015a4b858e3718b91adf1989f039f8c2d98c523f33b71838ddb623860e039a4d8727b7e29ce39a552c2f43b3fa0a0c9cc6b34864e47e829511a603901893be529299483423971a31c1dc65c6b3ca61aa0e66ca06c01016317aca065677592b062bec681b5301bca419790348ce78021a4e5024fb55b58c16292f59410a5af0016b3996f5fef6efb21a72439ba8222a764a04497b082565cd7ae454a52be15cc37beaba8f72c53ded746ab689c15d1357596432b94e6949c2d4f545b75fa8275eda00a5e43818d1b6d4e401704fc45ca747c8669fcc4f5f99b43c02758fa9d1825f7f8c48105f4f5099663ebc5e7b4bf653f2b5663ef2e649c92b28962138c8d25cbf6a3c1ffda6cac32ceec47180ff7b7b06bfe8ee3e1fef65f515e83adff886571294a0d1df3da7805134806ffbf709cdbf91eb60bf5ef8137c656e0d316f708015bd78534e0ef7193f2d79cf8536f38b077ad7a414b95617171dc0f699ed2a8cff9f9e46c1c4ad0e3fe276fa396a51a03fd110000ffff1bbebd06ed040000",
"56d831af18f731847e4733aa321128cb": "1f8b08000000000000ff84914fcb9c3c14c5d7b99fe2bec25b74906451bab1b89896a7bb3e14a6d0758c77348c26215e9d29e2772fd1e99f45a18b8b7239e7e477b8419b9bee085b0b60c7e023630e2233de313d380391b11d290310d9bacacfbefd12e96a1fdbb6aef2558fb46dca3aa6e8f4a0268a8b3587b8b3dccf8d347e548d1d6c1a758b9afda4c2ad5383ef3210cd88ff123a62d53307d50cbaa5514f4c31830240a9ce571d398a9a090f07b2f703de6d24e0ef81f01c024e1c67c3b882981683a727a3bc1c5f10291c4fcd285f5c671dc106709d9dc157ba9f43c8ff662ab1ffc35160ae43c0d3398412cde027fa94fc29242f4aa418d3f858ac2092b0c637e710561009a8c2693125881da3c2be04b181f89d523f7312bf30fc28d1686768c0aac6e78de437cbfd573b929f39ffb9fba0cdad8b7e766d6278fbee94ae282f64bc6b0b10c25e77b0aac65e5efa995b7f77b9e147f17edfff57a3b3c3fea8187c275f52813c4b9097b8fc721cc5f2ff9722db8ba6e4ed28263fa60e79da1cc4e977031189e7e860831f010000ffff0b01096679020000", "56d831af18f731847e4733aa321128cb": "1f8b08000000000000ff8491cfcadb3010c4cfdaa7d81a5aec60ac43e925c58714bedefa5148a16759dec822b224e4b59362fcee454efae750e861112c33a3dfb051e9ab3284bd05b0630c89b10451e8e099ee5c8028d88e540088625d9b2fa1ff9ae862efdbb6aecdab1a69dba4f54cc92b27274a8bd50fb1b13ccc5da3c3283beb6c1e794d8ac324e3d548174c01a21bf17f424f2c07e6283ba77a1ad5c4940aa800a434e168c853524cf8702087e0f0661301ff8884a71871e2346bc615c4b4683c3c199bf3e30591c3f1d08dcd8b37d6136c0097d96b7ca5db29c6f25fa61a87bf1c15962a463c9c62ac51bb30d1e7eccf21655523a59427a46a0591852dbe3bc5b882c840479c165d83d8318e38d42036107f52da674ee6179aef356ae535393cb6f8bc51f3ddf2f0cd8e14662e7fed3e297d3529ccbecf0cef3f1cf2159b33e9e0fb0a84b0971decd8e2d09c8799fb70f3a5e67bf571dfbf69d15bb77f2a5c30cd4b2e501619f29c96df8e47b1f2ed52157bd19cbc65d09db1acf63289784e1e36f8190000ffff399545b56b020000",
"5d243c2aa906cb9527df41e508cda83d": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece54efef9eff3fdef04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351ae6f3e9c2e430100c1d450e1e839c44d7df365f3eed6ed6ebdbdde7cbcde6ebfae66a1599e528b8fdbeba4c642f36b50dfbdad2f0a2e3e6e0f1ec6f85b9a8d83d60d418243eb64c41340592eabea8069563ef6da80cdc0d0060acb5ab6db44e30ea84a2b3678cab83fc783f9efc21e3a6b1421cce25bb4320c715ee1c8d07f176c835da466a57a37b30c73a82490cdca98fd7576a02aa9fa0ad3c050513d552d867aa751b59d871b312d7aaede96bf2c80731309ba623a420183bdb18284f30a244c294952380d113aa28bdd860cf5edb5e9ee862befc60727883a1bea0760da9c1cef6953ecfbb3f5afa77f31ebdb3aec6eae5157ce67f335196b3b2347d8437f8405773ce49aca47cf8a526002ab87c2e67cb625a4c8bb27fc8a5ffdbe6ef000000ffff0987409f7d030000", "5d243c2aa906cb9527df41e508cda83d": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece5eefcf3dfe7fbeb04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351acaf97cba30390c0843479183c72027d5f5b7cd974fbb9bf5fa76f7f972b3f9babeb95a4566390a6ebfaf2e13d98b4d6dc3beb634bce8b839783cfb5d612e2a760f183506898f2d53104d81a4ba2faa41e5d87b1b2a03770300186bed6a1bad138c3aa1e86c1ae3ea203fde8f277fc8b869ac108773c9ee10c871853b47e341bc1d728db691dad5e81eccb18f60120377eae3f5959a80ea8fd0569e8282896a29ec33d5ba8d2cecb859896bd5f6f43579e48318984dd31152108c9d6d0c942718512261caca11c0e80955945eacb067afadaf5fe062befc60727883a3bea3760da9c1cff69541cfc73f7afaf7f41ebdb3aec6eae5257ce67f73312b676569ca1cdf60035dcd3927b19272f14b4d005470b92e67cb625a4c8bb27fc89dffdbe5ef000000ffff82fe973e7e030000",
"5d2e61f4f8ab5957f172a990d9fb3baf": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2de202040000ffffbe75c21514000000", "5d2e61f4f8ab5957f172a990d9fb3baf": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2de202040000ffffbe75c21514000000",
"5e8471dec0685b7154cd71dcf0444643": "1f8b08000000000000ff9452df4b1b4b147e76fe8ac3be9880d9c57bdf12f270f10a5eb8b4c1daa752c2989c8c5b7777c699c9d2100236166c8b6d6c11c51f0fb6d8e24bb550b0582bfe31c926f1bf28b3d93585ea43e7e5ccccf9bef39df3cd380e44277bbdf397d7efcf07fb27f04fe93f18ec3d0721b9e6d0df5eef5d9c41d439ed5d7c8c3637fa3b67fd4e6778f505d87c6906a2771b30b7b050322ce23823d262bd96f0a24e7bb8ba963719c8c192d642e51da78a217a5ca05436e39c796857b8efc4d40af7728bf55a0da572886a049a3e85225871ee6fab4088eb0b2e3558ccd54bf5c598c838e34e2a1c9fe243bcb3e3ad5518f362c1311c7da11b77a1a8701d1a045c53edf240ddc0e2496965993284e8ed65b4f9ba777935d83a862615c2adb6ec668852b93c681927fbdbe7d18fce142477105d7e883eb5219c9e82f02fb06d9296aaa2cf6d8532742b6887d3239d7bf71766f3d03f588d36df0c4fbf452f0eaf778f8657bbbdeffbfd9dc3c1d6b151f87a7cbdfe0a32ddf641aedb3ec8769f1d75d73e03215c98c681f172aa51048b0ad72aa4a9cc8d5f7612cb0cb546a9cad4f3b250841af5141608491a837fd1e7d02400005254a0e4060c32e943a6bedab3c6d72c48d47519a83b010532618a3ca08d39f43c0e9938cce3ca1f531fceff7f1b39b952229bf46cd678f6b83015ae6dfea699760c328ba1ce5bceb2a49aab9c791e47d14679c9d4b46e80ad0249428b101f95323ea7ad40934c282d8d4901f58dffd3f0e817d37d2e5153a6b2c5c91a977ede32280b42eab955aa316f495ca9bb12abd6e4e3db0494485a4e446678a031d0bfe93c513cd0949911272b23cca8e0cf000000ffff54d4b889ff030000", "5d9b1138f620733adbad0acfb294d661": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b4b03030325b04c49666e6a7e690948d2b058890b100000ffffb9f9177936000000",
"5e8471dec0685b7154cd71dcf0444643": "1f8b08000000000000ff94924d4b1b411cc6effb29feecc504cc2eb6b7040fc50a164a1bac3d9512c6e49f71eaeece3833591a246063c1b6d8c616517c39d8628b976aa160b156fc30c926f15b94996455a81e7a49e6e5799edfcc33ebfb901c6e774ede5e7c3ee9ed1cc2bde203e86dbf0621b9e6d0dd58e99c1e43d23aea9c7e4dd656bb9bc7dd56ab7ffe03e8747102924fab30353353342ec7f707a6d95a75e84b5acdfed272deec400ee6b4162aeffb158c31e002a5f228e73440afcc43df5acb3cc8cdd6aa5594ca77543dd2e4258c836bf7eeba05c761a1e052834b999eabcd5a23e594fb29d8ceecc48e3c3b740b573e0bbc92632874fd361511cc2751c435d18c47ea52666f4acaf38422241fcf92b5f79db3f3defa012c122158a5e12dc62815e351c334d9dd3849feb44661b806c9d997e45b13e2b15188ef80e73969540543ee2994312ba3178f0d388f1ecf4ce6a1bbbb94ac7de81ffd4adeec5d6cedf7cfb73abf77ba9b7bbdf50343f87970b1f20e32ede66eaedddccdb65fedb797bf3b0e17e6dc407929458c834b04730be956e6b22e6ff85fa2a8354a552241908571a8924061c17186e782fb1872587400a42843914534933e62daa937693acd82445d939182db048561c813529fc220e019fb3b8d0bff6f7d3afdf026f7704989ac3d31c0d5ad6d2a11cc331fa5b9e740004051e7c1f5e725d15ce5cc93f88ad44b7326cab59a86a1370a4ec3714254cad49ab26d8ad292451422129abec7e0d9b592432e5113aa0c71a4ca6598778dce859804ac4234e65d890b3526b1e28e3cbf89a1c475c8048f3446fa1fce0bc5234da8c594079a41dcdf000000ffff1ddc747cee030000",
"5fbeeedba452fb00cc08114c465ccc6f": "1f8b08000000000000ff84904f6bdc3c10c6cf9a4f31ab9314f695ef6ff0a16942bbb081d2e41eb4f2c82b6c4b4692932d61bf7b99c52d4b5b5af01f31f3cc4ff33cb37583ed093b9b00c234a75c5181902ec54aa72a41483fda9effa9f0b752a921f61240c83ed4e372302e4dcd218c81df66c8b6a6d2cc43dfb8147d33dbd17621ca7fcb577233067794a0015e6dc60e6f78353eba7ac216d7c5cc9d75439fd3123ba501fc121d3e53a98f364435e1cd0a338f1adf41b005f34455b12f2fb7288d698cb95c29f575ff9766d3253750fecfa5694e85cc373b8d3f07bed85c4869105d28f630d23eb823fedf622ae613558aaf4adeef9e3edced1f5ef6bb8f9fa5c64d8b5282081e37d733ef20b84639f338fbe7659659e9db4b71d3620ce34526661b835394b30621cec00f87c332ca3965f8416a718ddeec62a87f405d93568af3c849b2a7e0b1dba2f3db1516e98df3bdb749e9dbbf933255f63199af4b6494f32bf037d32fb8da7d269bbbf476919f41a4621e4ea1aa4c55c319be070000ffffe08efaf7a5020000",
"64f157c0a5aaef8684ce174785fdb08b": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2de202040000ffffbe75c21514000000", "64f157c0a5aaef8684ce174785fdb08b": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2de202040000ffffbe75c21514000000",
"65c9c5ceead4379a32ef56fe8044a9a7": "1f8b08000000000000ff8451cb8adc30103cabbfa2f121486191be604ec9924b7612f2f8008da6ed15634ba2255b0bc6ff1e641b1672d9435fbaaabaaae864ddc30e84032707e0a714b9a004916ed8adab7e89f79f4cbd7fdbb675d5573bd1b6199b7c0720bac197d7f9a65d9ccccd8fbe8d79b02d319bf4188c8ba137c98ef6ee43f7313d50319c9ca996ef143a5000c6e0952a06aa68f784988917620dfd1c5cc3645e1ca69bfe4a53fcbd630a65cdf8f9b8a28fdd1312739bc80a57108b656487b9f0ec4a5b8883f79fec4b0cbd1f406c209afe826719fd8d8aec5a1e5de234764aff0d93e5fc6ac73f3f5ebecb4fec1408dfefae9777d933f33596e7379f0fd3e368f0e36e51335ef0f4bf523d2248766718d57ea27fd1e073217eef2b6b3e19523d615e9a75cd47e30b36b0582e5281602a3307d8e05f000000ffff90051aa3f4010000", "65c9c5ceead4379a32ef56fe8044a9a7": "1f8b08000000000000ff8491cdaedb201085d7f014532f22a82278802aab56eaa649abfe3c0026638262031a885dc9f2bb57d8496feee6dec56c38c377ce8164ecd5380447c972ee8714a980e02cb5d0ccb33ac6f30fc2ceff5d9679562733e0b268937cc3396b9c2f975bab6c1c74eb7b5f475fc9949875ba3a6d63e87432bd39fbd0bcbf1eb0684a564f86ce181a2e39d71a4e3841c009cc9a1032d288a478770bb66a228f1652abbee0107fad9a043165f8b851d476b60724aa1349c2ccd968a87664b673f06af1730c9d775529704fae7e7f3f7ee34c72e6bb1573f8af7cc5229a1a4b9538f48d547fc260285f4c2f76b6c84febfa870304df575746586e14385b9e58b66c98cdff99517dc5ce76ee4dd094e1f0e870c269c36cd7ea27aa9fe87c2e482f0f24a67c6f2be41ef26865a5ecef79aa580c1521f9c366e1ff020000ffff986586fe25020000",
"6640f2771831eddce9f1132a8ffa02b1": "1f8b08000000000000ff8c90cd8adb3010c7cfd6534c75285258a44be9a5e4d0dd855e36e9f7038cf515115972e4719362fceec58e0ba5a73d0c0231bff97ff468ce181c582c8cc5ae2f9540b0869b92c9dd8833d6f069528762bf54e7e36d9ea7491db173f3ac6326573326dd15eb12670d0f914e63ab4ce9741b535c469f2b5219747f0eda94ec758f096dccaf58b748d8e2e0f470499c49c6fc980d1cddf5f9514810b685dd7049eaf9f1015cadcb942a6162cd2fac607c8081ea6868f9699e527499eec053c93e06d6ccac897e45f7b0b9529f1c096e5b45a54b5caa9fb9c33a9c30fdf87c78116f8d0ff2c34abcd9438e693d5d1d8d35afe76c0b7b58248eee7af8fdfdeb8b303ea8bbb6647f37e72d89b0b0b358247cc3ebc74ad124270cdd60eb7ef1b9bc0f102dc44cefdf49105809766bdf6a43fe0faf350447b09407be960e6cfb8ff29f000000ffffed2515fbf0010000", "6640f2771831eddce9f1132a8ffa02b1": "1f8b08000000000000ff8c51cb8a1b31103c4b5fd199c32219235d422ec187ac1772899df707b45eb3c21ac9d6b4638761fe3dc899049343d8432350775575571dd11eb0f7e0b0701e8763a90482b3ce964cfe4a1de7ac9b26b52bee53f5215ee7799ad41e073fcf3a66f23563d243713e759c757da4e7b351b60cdac4145be943452aa33e1e7a6d4b0efa88095dcc2f1877486870f47a3ca58e4bcec3395bd8fbcbd3a390209c81d5784aeae9710d36406b0ab9065f6bab52254c9cfdc0daee6136f4d086b72587d8b70f826513f5ede3ee036792b3186ee8cddfce7b4fa2734651195227d5f73c601d9f3189074bf2ed6df8d506724c4d8a554fe79a399bef982cfd26d9a6e833dd733455f16043ff5f226760735b7cef2fbb9f5f3f2f10ce6c80cd72334ccea86d2aa31772e67fd0f3e29770b07258247cc1cbbb4ad1262f2c5d6149b839d2de35440731d39bd712045682d52d55b540fef5556be83d418b08422d033873a7fc2b0000ffff866476e156020000",
"676482aadd24e9539226c67ebd8b5d04": "1f8b08000000000000ff8c90cd8adb3010c7cfd6534c75285258a44be9a5e4d0dd855e36e9f7038cf515115972e4719362fceec58e0ba5a73d0c0231bff97ff468ce181c582c8cc5ae2f9540b0869b92c9dd8833d6f069528762bf54e7e36d9ea7491db173f3ac6326573326dd15eb12670d0f914e63ab4ce9741b535c469f2b5219747f0eda94ec758f096dccaf58b748d8e2e0f470499c49c6fc980d1cddf5f9514810b685dd7049eaf9f1015cadcb942a6162cd2fac607c8081ea6868f9699e527499eec053c93e06d6ccac897e45f7b0b9529f1c096e5b45a54b5caa9fb9c33a9c30fdf87c78116f8d0ff2c34abcd9438e693d5d1d8d35afe76c0b7b58248eee7af8fdfdeb8b303ea8bbb6647f37e72d89b0b0b358247cc3ebc74ad124270cdd60eb7ef1b9bc0f102dc44cefdf49105809766bdf6a43fe0faf350447b09407be960e6cfb8ff29f000000ffffed2515fbf0010000", "676482aadd24e9539226c67ebd8b5d04": "1f8b08000000000000ff8c51cb8a1b31103c4b5fd199c32219235d422ec187ac1772899df707b45eb3c21ac9d6b4638761fe3dc899049343d8432350775575571dd11eb0f7e0b0701e8763a90482b3ce964cfe4a1de7ac9b26b52bee53f5215ee7799ad41e073fcf3a66f23563d243713e759c757da4e7b351b60cdac4145be943452aa33e1e7a6d4b0efa88095dcc2f1877486870f47a3ca58e4bcec3395bd8fbcbd3a390209c81d5784aeae9710d36406b0ab9065f6bab52254c9cfdc0daee6136f4d086b72587d8b70f826513f5ede3ee036792b3186ee8cddfce7b4fa2734651195227d5f73c601d9f3189074bf2ed6df8d506724c4d8a554fe79a399bef982cfd26d9a6e833dd733455f16043ff5f226760735b7cef2fbb9f5f3f2f10ce6c80cd72334ccea86d2aa31772e67fd0f3e29770b07258247cc1cbbb4ad1262f2c5d6149b839d2de35440731d39bd712045682d52d55b540fef5556be83d418b08422d033873a7fc2b0000ffff866476e156020000",
"6a0765f64b1e9febbe82b717286415c5": "1f8b08000000000000ff2a2d4e55c82e4a2cc92f8e4f49cdcdb7e6e2f2f40b760d0a51f0f40bf157482c2ac94cce492dd648c84c49d0514828c92cc9494dd0540873f409750d56d030d45150078ba96b5a7301020000ffffb60f97194b000000",
"6cc24b961eaafa6a5726c5e875dd92ae": "1f8b08000000000000ff4ccc41cac2400c05e0f5e414610e5092fefc28822bafe04e5c0c4d16814ea74ca35e5fa22ebacbfb1e2fb7cb6cbaf81dd252aae219b3686d19d2da9bb7c83ead195211e991783c0c34d0c027e691399ac9ed19cb7f826432c7c90449accc57abda1efe1912d52d43ea5a64c7e38f5fdd5c77fef77544c4f8b96b8eb46578070000ffff6f600d93b7000000", "6cc24b961eaafa6a5726c5e875dd92ae": "1f8b08000000000000ff4ccc41cac2400c05e0f5e414610e5092fefc28822bafe04e5c0c4d16814ea74ca35e5fa22ebacbfb1e2fb7cb6cbaf81dd252aae219b3686d19d2da9bb7c83ead195211e991783c0c34d0c027e691399ac9ed19cb7f826432c7c90449accc57abda1efe1912d52d43ea5a64c7e38f5fdd5c77fef77544c4f8b96b8eb46578070000ffff6f600d93b7000000",
"7a53e746d0de690c8b20ca83292508c5": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b0b03030325b04c49666e6a7e690948d2b058890b100000ffffb7699cdc36000000", "7a53e746d0de690c8b20ca83292508c5": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b0b03030325b04c49666e6a7e690948d2b058890b100000ffffb7699cdc36000000",
"80a49866e2154ebe00c57fd7c80a4cab": "1f8b08000000000000ff8c51416e8330103cb3af5871b253845fd043d25c7a481435fd80c11bb20dd89631a112e2ef15904655a54839793d339edd1d2b852f45c7b5c19e03b1fda2328252f879265cf0a82b6cf4855a6cbb4018cf846dec0ae416ad8bb32822db9938b1d5f5f22e07f0babce88ad0300037de858802125f603a0cf9ce9943a0137f8fe330e47bddd0382aed3985e421cd3652b0ba5646bba7742d852b0555055f3eade792528024ad389ebb222f5da32ae7aa9ad494500a12e0aa031aed0ec15dd950c0d739bc7c4ffd91a230da4d6586b762bbb9971f64b8bddf766f72b6ba757d60776317cb99d8b035c2522f7c916fa971c7794b99e184ad7ef5c7e59452029c3a5be2bbe5b8f65e4814abb5f7194ea8901952082e481c20f1da72299626d3278a3f5b66ffe7cc70ca75996b4ffdda7b2961849f000000ffff98b3536b52020000", "80a49866e2154ebe00c57fd7c80a4cab": "1f8b08000000000000ff8c90316ec3300c45e7f0148427bb35a4bd5bba756890a11750644661638b024d27050cdfbdb0d3a163d6c7f781cfef3dbe9e26ee3bbcb312e76f8a06dee3d785f0c12d241cc295461c2725b40be168d30979c42cb649869cb7c39973e81f39075042bc8644d831000f45d4b0865d35cfee53baa3d2997f96659edd210cb42c9eb391e6d0fb2e48f58c3792de38d2d32ea94f5a6205b0ab12db653ab928834f22a927bffe5f4103e07d92b744993418e15583c988b6ed03e72947fcc86cfb52ea06eb977d292daeb46e5a2455d10667d8959039d66bc4bdaf6bd45d107754b97147dae25ff37f642de60e746ff140f77d294d030bfc060000ffffe672418b9d010000",
"885a5148286f0720126cd2a540b56564": "1f8b08000000000000ff4ccc41cac2400c05e0f5e414610e5092fefc28822bafe04e5c0c4d16814ea74ca35e5fa22ebacbfb1e2fb7cb6cbaf81dd252aae219b3686d19d2da9bb7c83ead195211e991783c0c34d0c027e691399ac9ed19cb7f826432c7c90449accc57abda1efe1912d52d43ea5a64c7e38f5fdd5c77fef77544c4f8b96b8eb46578070000ffff6f600d93b7000000", "885a5148286f0720126cd2a540b56564": "1f8b08000000000000ff4ccc41cac2400c05e0f5e414610e5092fefc28822bafe04e5c0c4d16814ea74ca35e5fa22ebacbfb1e2fb7cb6cbaf81dd252aae219b3686d19d2da9bb7c83ead195211e991783c0c34d0c027e691399ac9ed19cb7f826432c7c90449accc57abda1efe1912d52d43ea5a64c7e38f5fdd5c77fef77544c4f8b96b8eb46578070000ffff6f600d93b7000000",
"89e787ea2b6d77d3061b5e56a50c6e36": "1f8b08000000000000ff8c91cd6ae33010c7cfd653cc0a769182911f60c9291bc2c26e1a9af45c14595244648d91e53450f2ee45b25328bde42004c3ffe3374c2fd5595a0dad44425cd7634cc048451586a4af89125251ebd2693c0a855d7374dee5d79ca34c3834fdd9364aaa936ea26edd401f5063304d2fbd6c5d7840eed152c209316350b0d56fcfb98671601116a55294490d3ac6fc30727827d5454650c6c290e2a8529e542bef744877d70a8371965437523953cc4b98a9c44627462759c2ce532e5e4227e37092fef0f4ff1ffba58ce5bf8be9c71282f3253fea34c6501273d8e4ff2456c68a898093bbf436afc55a58b41239ec5cb0b33c5d613e4146cd3f07f6754767e0b59ed15b31f5fdc16cad81eed7075a03ed5db0e5c760e977668f56ac7320cb070f62af13dbfddd6ef854c37e5e382d157cda6be6fe080000ffffb73c6a1735020000", "89e787ea2b6d77d3061b5e56a50c6e36": "1f8b08000000000000ff8c52df8a2a2118bfd6a7f88e704263701ee0d05527e2c0a98dadbd5ecc51931c1d1c6b83e8dd17c7215a16962e44f8e6fbfd1d3b218fc2286844c0d8b65d8809284644069fd425118c1131361d4e7b2e435befadb3f9d4c72852e8ebee686a29e441d55135b6274f6c07afeb4e38d158ffc4ba0b866086b13e79096bf5f19a6528031a613a48f2615281d4907728ab40c5984f880cae189d45cc8990d4060a621ebcb6268f128c4ef84a7418318cac1ee0b3fb87a54a94145c0aad238cbff956c4fe201c9dc8c4fe0cfbbf66e0adcb7228aa748a1ea3db03994c8567eeacf2e99163f7b2fa4f27529b1f893247f170af60c0602435ccc6e0d7c8e72ef48ab28c28e0dbd81c6d60da88c06063bd2904325d60fccbb9917c33a05fbbb31adeab3143c38b83bf21432b20dbc58e54403aebcd70076fc8f7142e18bec88434bf29cfb72ad1cdbff5921519fafbccc820c14ad2d1f767000000ffff7e2fc7cb98020000",
"8f2519501a642ae50acf464ad3acb9f9": "1f8b08000000000000ff8c51c16eab30103cb35fb1e264e721fc05ef90bc5cde2151d4f4070cdec036605bc6844a887faf8034aa2a45cac9eb99f1ecee5829fc53f4dc181c3810db0f2a232885ef35e18a475d61abafd461d707c2581376b12f903bb42e2ea2886c17e2c25637ebbb1cc0ebf2aa2b42c300dc7a17220a487c81e938e607674e812efc394de3981f754bd3a4b4e71492a734db48c1ea4619ed5ed275146e14541da37f59cf25a500495a71acfb222f5dab2ae7aa86d49c500a12e0a6031aed4ec1ddd850c0bf4b78f99186334561b49bcb0cefc57ef728dfc870f7b81dfec9c5eadef589dd9d5d2d1762c7d6084b83f045bea7d69d972d658633b6f9d69fd7534a0970e96d89ff2dc7adf742a2d86cbdcf704685cc90427041e20889d7964bb136993f51fcd832fb3d678673aeeb5c471ab6de4b09137c050000ffffe1cf2bb052020000", "8a7d67b864f45201854ef2ad00b51b09": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"8f2519501a642ae50acf464ad3acb9f9": "1f8b08000000000000ff8c90316ec3300c45e7f0148427bb35a4bd5bba756890a117506c4666638b024527050cdfbd70d2a163d6c7f781cfef3dbe9e661e7bbcb112a76fea0cbcc7af81f0c12d449cc2850a9659096d202c369f900b26b1bb64c8e97e38730ae323e70072e82e2112f60cc0531635ac61572d8bfb94fea874e69f755d16770813adabe764a4298cbe0f523de315d22b77f4b44bea07b35c01ecaac836cc27d7c9e4a3481cc96fff57d000781fe52d52220d4678d16052d0eefbc0794e1d7e24b67dce7583f5cb3ee716375a372d92aa68830bec7248dcd55bc4bd6f6bd47d107754b9724fdae25ff37f642be60e746bf140b77dce4d03eb6f000000ffff14b8957d9c010000",
"959fd518960ea8b397538a6f7b1bdd3a": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000", "959fd518960ea8b397538a6f7b1bdd3a": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"95d28ebee82ae43dfc0c8b16b6088b2d": "1f8b08000000000000ff5ccdc14ec3300cc6f1f3fc143ec2614e9c32525e827748db6022927964c98434f5dd51e15238f862fdfefa8a2e3d47bcdfe93594b8ae00a2c8c40ea0c6cf9e6ac407404494d4defb44b31633a59cb6331f3534bd6209d7162b1c764454d45caa369dfa1bde981cf13f90c359fe90811c1c7effa455cc9739c786374b96ecd1597eb1cf6ee4f1343c9d8e4be0c1cf7ef4bcf82d52c99176add4cbfc33ebc8c2237c070000ffff34bdd5b6e6000000", "95d28ebee82ae43dfc0c8b16b6088b2d": "1f8b08000000000000ff5ccd414e03310c85e1353e8597b0a81327940c97e00e9999602292baa4498554f5eea88505edc22b7fbf5ed5759484a713bdc59ace67005164620fd0d2d7c82de12320224aee1f63a645ab9973c997339f2d763d608d879edabd121535fba65de7f18e4726477c310f37a6c49ddc284fee575d5fa44dccb7d9a58e474b96ecc6597eb52f6ee269eb9fb79b35b20f4b9802afe1af532989fee5d2f6cb75df918527809f000000ffff3ae05435f3000000",
"97e4f2cf9f4ad4fc842f20a7fb124f91": "1f8b08000000000000ff94924fcbd43010c6cf994f3116947629cd41bc54f6b0caebcd176105cf693a6f1ab64d423aedae947e7749bbfe4578f510128627bf799e6182d21765085b0b6087e023630e22d3de31dd380391b11d280310d9b2541f7dfb29d293bdadebb2548f6aa07595d63145a77a39529caddec5c672373595f6836c6c6fd39197a8d88f325c8cecbdc94034033e2774c4b2630eb2e9554b831a9962f63c3f7d8b41cbab8a2db90c0a00298daf0d398a8a09772db2f73d5e6d24e0af81f014028e1c27cdb88018678d877ba8eabcdf20921b3c3443f5e08c7504c2c4a0f1b077da64146105789a9cc647ba9e42c8ff462ab1fb0553a2f9835160ae42c0c329841275ef47fa9088099b1725528ce9f8582c2092f088af4e212c2092ef1ac759972036b73576e9997cd6684a102b889fc0e31d99120bcdb712b5729a7aac8f785f83ea8be5eeb31dc84f9c7fafbd53fa62a29f5c9becbc7e73488b529d497bd71620847dda3cd64734d5b99bb8f557976bbe156fb7fa8b233adb6f4d45ef4df590b2e45932798ef38f1f7bc6fce55c645be6445e7fa377ff414fd3f817fa38ebea7d9a509e2afb3cd273051189a7e860856f010000ffffd0e332643a030000", "9633293b1618913c69833784cc3e25d2": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b0b03030325b04c49666e6a7e690948d2b058890b100000ffffb7699cdc36000000",
"984dd6df0bfb1684d6d188b40962ca7b": "1f8b08000000000000ff8451cb8adc30103cabbfa2f121486191be604ec9924b7612f2f8008da6ed15634ba2255b0bc6ff1e641b1672d9435fbaaabaaae864ddc30e84032707e0a714b9a004916ed8adab7e89f79f4cbd7fdbb675d5573bd1b6199b7c0720bac197d7f9a65d9ccccd8fbe8d79b02d319bf4188c8ba137c98ef6ee43f7313d50319c9ca996ef143a5000c6e0952a06aa68f784988917620dfd1c5cc3645e1ca69bfe4a53fcbd630a65cdf8f9b8a28fdd1312739bc80a57108b656487b9f0ec4a5b8883f79fec4b0cbd1f406c209afe826719fd8d8aec5a1e5de234764aff0d93e5fc6ac73f3f5ebecb4fec1408dfefae9777d933f33596e7379f0fd3e368f0e36e51335ef0f4bf523d2248766718d57ea27fd1e073217eef2b6b3e19523d615e9a75cd47e30b36b0582e5281602a3307d8e05f000000ffff90051aa3f4010000", "97e4f2cf9f4ad4fc842f20a7fb124f91": "1f8b08000000000000ff9492cfaadb3c10c5d79aa7984ff0153b186b51ba71c92285db5d2f8514ba56e4892c624b421e2729c6ef5e64a77f29dc76216c8633bf396798a8cd455bc2d601b82186c45880902678a63b4b1092dd401240c879ae3f84f663a2b3bb2fcb3cd7cf7aa06551ce3325af7b3552ba3ab389ade36e3ad5260ceae47a979fba24cd6154f162551fac04711af025a127561d7354a75eb734e89129c997f9b92d45a36e3ab5e42594004ad9d058f29434136e5ae4107abcb944c05f22e121461c394d867106315e0dee1ea1eae3f60591dde0ee34d44fde3a4f206c8a0677dba45546091680f3e40d3ed3ed1063f1275285dd4f980aed6f8c120b1d23ee0e315668fa30d2fb4cccd8a2ac9052ca2fa4720691857b7c75887106917d37385e4d056275db60977fb3cf066d056201f103b87f20736261f85ea1d1de508fcd1e1f67507f76dc7d720385898b6fb577da5c6c0a936fb39dd76f76f950ea2399e0db128470e7d563b3475b1fbb89db70f385e17bf976adffb747effa75a8e883ad9f7296426693c774fddeb1652cfebf9672cd9cc9cb2ff4ee1fe8791b7f43df365094ebaa12f1943c2cf0350000ffff549ece532c030000",
"984dd6df0bfb1684d6d188b40962ca7b": "1f8b08000000000000ff8491cdaedb201085d7f014532f22a82278802aab56eaa649abfe3c0026638262031a885dc9f2bb57d8496feee6dec56c38c377ce8164ecd5380447c972ee8714a980e02cb5d0ccb33ac6f30fc2ceff5d9679562733e0b268937cc3396b9c2f975bab6c1c74eb7b5f475fc9949875ba3a6d63e87432bd39fbd0bcbf1eb0684a564f86ce181a2e39d71a4e3841c009cc9a1032d288a478770bb66a228f1652abbee0107fad9a043165f8b851d476b60724aa1349c2ccd968a87664b673f06af1730c9d775529704fae7e7f3f7ee34c72e6bb1573f8af7cc5229a1a4b9538f48d547fc260285f4c2f76b6c84febfa870304df575746586e14385b9e58b66c98cdff99517dc5ce76ee4dd094e1f0e870c269c36cd7ea27aa9fe87c2e482f0f24a67c6f2be41ef26865a5ecef79aa580c1521f9c366e1ff020000ffff986586fe25020000",
"9b304970a0564dd9317fcd5d626e58a4": "1f8b08000000000000ff2a2d4e55c82e4a2cc92f8e4f49cdcdb7e6e2f2f40b760d0a51f0f40bf157482c2ac94cce492dd648c84c49d0514828c92cc9494dd0540873f409750d56d030d45150078ba96b5a7301020000ffffb60f97194b000000",
"a17964c54f014a0dd59c42b49123a941": "1f8b08000000000000ff5492b18ed4301086ebcc530c96901294b5fb95b65836cd35b72be005bc5ec7589b782c674240e80a3a4a0a7a90780c5e0771af81622f3a5d916226ffffcdf8b7a33657ed2ceae8c18f9112630d953014d87e640195e847160095709edfcf67696854673ff8f553d7a4992615af4e05cb2a45a3169d2e361407911bac7434e8e02425a75c8a464003a014ee63bceb5082a130f1addaa17877ec8e5bdc771dee4f27bceb4416dfdbe530781b18835d70c5a0c935f473304fbf6bd33b7c557690a575a0d07bd722459e504ab99a65e7f5708cec2934587776a4a26dd1a644a9c1cf50153e6e7778c33d1b527852ca062a63b26f951653c6d7b70ce56b6dae2ed11c2e75d3623fb27c1b930fdcd7e2e227431f6cfab455ea627b3d0fac5e4ea22d71340d54becfe8173b0c7e58d7aa92e53985b5cc53a17a80ffbd7bbb3c9da536a66957193ce4081fbffff8fbf51bba37a703fef9fdebf1e71750cad1d6d96093668be5329189068c89980c6e3639eacde63cae2f44e636fc0b0000ffff940f602534020000", "a17964c54f014a0dd59c42b49123a941": "1f8b08000000000000ff5492b18ed4301086ebcc530c96901294b5fb95b65836cd35b72be005bc5ec7589b782c674240e80a3a4a0a7a90780c5e0771af81622f3a5d916226ffffcdf8b7a33657ed2ceae8c18f9112630d953014d87e640195e847160095709edfcf67696854673ff8f553d7a4992615af4e05cb2a45a3169d2e361407911bac7434e8e02425a75c8a464003a014ee63bceb5082a130f1addaa17877ec8e5bdc771dee4f27bceb4416dfdbe530781b18835d70c5a0c935f473304fbf6bd33b7c557690a575a0d07bd722459e504ab99a65e7f5708cec2934587776a4a26dd1a644a9c1cf50153e6e7778c33d1b527852ca062a63b26f951653c6d7b70ce56b6dae2ed11c2e75d3623fb27c1b930fdcd7e2e227431f6cfab455ea627b3d0fac5e4ea22d71340d54becfe8173b0c7e58d7aa92e53985b5cc53a17a80ffbd7bbb3c9da536a66957193ce4081fbffff8fbf51bba37a703fef9fdebf1e71750cad1d6d96093668be5329189068c89980c6e3639eacde63cae2f44e636fc0b0000ffff940f602534020000",
"a2cb44570c3d3285165729786d5f1def": "1f8b08000000000000ff9452418bdb3c103d6b7ec57c860f2c486d7a0dcda194b69bc386b449ce65228f9d21b2642499ee62fcdf8b9c65d9c01eda838d34f39edf9b371ec85ca963ec491c80f4830f094b50456ba92b40153edede7594ce91cd97f81c0dd9e598a4e7024015d3543dfa661fb895a7799ea66a473dcf732d2e717064eb4632be937419cf95f17d7d162bf9a9af81928ff570ed6ae35d5b0f64a911f71770ebbb0234403b3ab34c506a9c4065ebd59e42e45283b2beabb64e52e9c46aac6b6cf83c7698416bcccd46c2661a285d66500db71c96ea17ebdff25b5f16af53614c1452a141bd78bd096850bf566832f1dbe8cc0a39045c6fb091a5ff79183244daa5fedf069dd86c570de4c4941c820635833299d3d3954b7321873e568725fa157ed4a06e6ba8763e49fb5c9a15be6ca33a6cbf3f9cf677f71fa7edf1ae70fcfaf3f1aeb0dd1d35a8d687c548ccca9f3e18506fa6ee3821e14d16ff8fc50a637548415c576a9d49bf25990bc6e50b8622ffb3833528a55e63cb19a97753e7275942572aff76d5c1320fe5edc8c6bb6669054e6370ef587938edb350c32d8d36adefb0730e7e863f010000ffffe9e8e3430d030000", "a2cb44570c3d3285165729786d5f1def": "1f8b08000000000000ff9452418bdb3c103d6b7ec57c860f2c486d7a0dcda194b69bc386b449ce65228f9d21b2642499ee62fcdf8b9c65d9c01eda838d34f39edf9b371ec85ca963ec491c80f4830f094b50456ba92b40153edede7594ce91cd97f81c0dd9e598a4e7024015d3543dfa661fb895a7799ea66a473dcf732d2e717064eb4632be937419cf95f17d7d162bf9a9af81928ff570ed6ae35d5b0f64a911f71770ebbb0234403b3ab34c506a9c4065ebd59e42e45283b2beabb64e52e9c46aac6b6cf83c7698416bcccd46c2661a285d66500db71c96ea17ebdff25b5f16af53614c1452a141bd78bd096850bf566832f1dbe8cc0a39045c6fb091a5ff79183244daa5fedf069dd86c570de4c4941c820635833299d3d3954b7321873e568725fa157ed4a06e6ba8763e49fb5c9a15be6ca33a6cbf3f9cf677f71fa7edf1ae70fcfaf3f1aeb0dd1d35a8d687c548ccca9f3e18506fa6ee3821e14d16ff8fc50a637548415c576a9d49bf25990bc6e50b8622ffb3833528a55e63cb19a97753e7275942572aff76d5c1320fe5edc8c6bb6669054e6370ef587938edb350c32d8d36adefb0730e7e863f010000ffffe9e8e3430d030000",
"a416686e4cfcf5ed8366cfcf264e48e0": "1f8b08000000000000ff8c53dd6ef3360cbd969e82358ac00e1209dd865d78f0c5d66c4381b52bf6735dc812ed0891255796d71481df7d90ecf46718be2f01624914299e7348f6421e448ba084a35477bdf301724a32e96cc063c828c982ee30a39464a713bb77ead163a38fd3743ab107d1e134716d037a2b0cef9c4213435a1df663cda4eb78ad8d8e7f7ef022b881f787964b21f7c83becd2e6e2008f4a0f97783bdbf05e18a1b4bdc05d89206a31201f9e2f013fbc5ac97bdda3d1167923ac1ba34cc728137c2d78d6b2a094f3d6952d5af42220cc1e109c33d0a2adc34039879d70b12e90f46d84441a5e7b4ce637139c28b9356ec0bca0e451db3697e1084bf5d8edbc1690a3f780de3b5f50c239d46128616b476392b4d52a958efde88396064f77bb727b33c156ee511e9ea2db93740aabebabca6ab35a5db3bb5d556d6f28592272f9df9c1bd02ac2fcfebb02f2f5a7e737672453d4215154c2b1995d3c0dc18f32446aaa86b7df7a78366cf71325a90fcec674607fc42f259dfce07eee2f76bf6c28490bace7a2b15fd24289c2cefd7cecb5c708f8db6f165c0ff802165f40244cc22af018466f196d462be375ee3fe5df4027ff27ed06547d065f40ae620193048b0c91e73fc2836cda85f98912b27b07955a8bed462f827696928912dda4072a58da9cfd8a21cf44df1b2d93170bae3359c1feb69df0c35e98bf7ebfff2d5fc9a62d7e48a15715586d626e32d34aef2aa860a5848b665597a0ea4d72507a28c1c77d274be864dc2572252c624639b2799e8b78fb2e6a39ab9a7f6291cba665ef1c0be090eeff44e9ac8a2f4cf40c6c2e47ea7290e91bf6081e07377a894b3972056b255c01cb34a4ee619d646fd3a1d85cab0f06557f3ccd653b1be6ac71a4a08f9f2fe5bc68f022a29951549e4ef4df000000ffff20759cb67c050000", "a416686e4cfcf5ed8366cfcf264e48e0": "1f8b08000000000000ff9c545d8be336147d967ec55db3047bc8486c5bfae0e287eeb82d0b9d74e8b6cf8b2c5d3b22b2e495e54d96e0ff5e243bf351ca346c20967c75753fce39d7839007d12128e128d5fde07c809c924c3a1bf014324ab2a07bcc2825d9f9ccee9d7af0d8ead33c9fcf6c277a9c67ae6d406f85e1bd5368e2954e87fdd430e97ade68a3e39f1fbc086ee4c3a1e352c83df21efbb4b9fa8247a5c76bbc9d6df9208c50da5ee1ae44108d18918f9faf297efc6a251ff480465be4adb06e8a309d224cf07f971fb17ce6d739d719e447ed31a305a55f848707efbe68851e2a8876b6c3e3470cf90e8f5bd8e1b17e9f963f232069777f5750ca79e7ca0e2d7a111096ac109c33d0a16dc24839875ab8c83524ce5a219186af0326f3a309ce94dc1937625e50f2a06d97cb70825511ec6e590bc8d17b40ef9d2f28e11c9a3096706b2763125dd526c981fdec839606cf1feaf2f6dd0cb7728ff2f029ba7d924e61f5f64d65b5d96cdeb20f7555ddbea364bd91cb7fe7dc8256b1cc1f7f2820bf79117e7ba9648e38a41695706ce92ebe8dc14f32c4d654038fbf9bf1b361f57b4a92b62ec6f4c212ba94f4f299fb45b3ec7edd509216b85984c07e4d0b250a7bf7cb69d01e63c1df7fb7d6b5c323583c82483509abc06398bc65b49dac8cc7b97f917f0bbdfc8fb45b50cda5f802721509dc826c2186c98b84c68a486c79491233d7c2e53e068d11125a29f1e5e49b72dfa85793473dcbb65b19385342ea2770d2d8b07af2226867299929d16d0a50c13ac2ec370c792686c16899bc5870bdc90af6b7ed851ff7c2fcf5c7fdeff946b65df153bafaa602ab4dccbd769ee22aa860a3848b66d594a09a6d72507a2cc1c77d2fcb880c250ba925aca4465ab2e55b55c4d32772cb85ddfc4517b96c3bf6d463011cd2f94794ceaa1861a644b650816269ce2e04ad22493690e919f6081e47377989ab4856c40b586734699a2d1c5dc6760914671786f8782dcc5513fe5c45dad099fe130000ffffba9a548b39060000",
"a7f82d82b0fbcd0d7a86744fc49b7173": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000", "a7f82d82b0fbcd0d7a86744fc49b7173": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000",
"a833afd1c2dfd51f0ba59a8bf977cc1b": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000", "a833afd1c2dfd51f0ba59a8bf977cc1b": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000",
"aa6f74a5b61f4cf11f0d49914680fd21": "1f8b08000000000000ff8c91cd6ae33010c7cfd653cc0a769182911f60c9291bc2c26e1a9af45c14595244648d91e53450f2ee45b25328bde42004c3ffe3374c2fd5595a0dad44425cd7634cc048451586a4af89125251ebd2693c0a855d7374dee5d79ca34c3834fdd9364aaa936ea26edd401f5063304d2fbd6c5d7840eed152c209316350b0d56fcfb98671601116a55294490d3ac6fc30727827d5454650c6c290e2a8529e542bef744877d70a8371965437523953cc4b98a9c44627462759c2ce532e5e4227e37092fef0f4ff1ffba58ce5bf8be9c71282f3253fea34c6501273d8e4ff2456c68a898093bbf436afc55a58b41239ec5cb0b33c5d613e4146cd3f07f6754767e0b59ed15b31f5fdc16cad81eed7075a03ed5db0e5c760e977668f56ac7320cb070f62af13dbfddd6ef854c37e5e382d157cda6be6fe080000ffffb73c6a1735020000", "a8de4218a101c7dbc4005b492e2f7fa1": "1f8b08000000000000ff2a2d4e55c82e4a2cc92f8e4f49cdcdb7e6e2f2f40b760d0a51f0f40bf157482c2ac94cce492dd648c84c49d0514828c92cc9494dd0540873f409750d56d030d45150078ba96b5a7301020000ffffb60f97194b000000",
"aa6f74a5b61f4cf11f0d49914680fd21": "1f8b08000000000000ff8c52df8a2a2118bfd6a7f88e704263701ee0d05527e2c0a98dadbd5ecc51931c1d1c6b83e8dd17c7215a16962e44f8e6fbfd1d3b218fc2286844c0d8b65d8809284644069fd425118c1131361d4e7b2e435befadb3f9d4c72852e8ebee686a29e441d55135b6274f6c07afeb4e38d158ffc4ba0b866086b13e79096bf5f19a6528031a613a48f2615281d4907728ab40c5984f880cae189d45cc8990d4060a621ebcb6268f128c4ef84a7418318cac1ee0b3fb87a54a94145c0aad238cbff956c4fe201c9dc8c4fe0cfbbf66e0adcb7228aa748a1ea3db03994c8567eeacf2e99163f7b2fa4f27529b1f893247f170af60c0602435ccc6e0d7c8e72ef48ab28c28e0dbd81c6d60da88c06063bd2904325d60fccbb9917c33a05fbbb31adeab3143c38b83bf21432b20dbc58e54403aebcd70076fc8f7142e18bec88434bf29cfb72ad1cdbff5921519fafbccc820c14ad2d1f767000000ffff7e2fc7cb98020000",
"aaa0e84aef1077c2699e21ba05d51c7f": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a4cbe9389e09c124f7598a083cb9bdff21c6f96e45ebcb7fbb95109ab2ecedd3cc758ffd746b7125fc060000ffffe2756aadaa000000", "aaa0e84aef1077c2699e21ba05d51c7f": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a4cbe9389e09c124f7598a083cb9bdff21c6f96e45ebcb7fbb95109ab2ecedd3cc758ffd746b7125fc060000ffffe2756aadaa000000",
"aaf0b28d854f8d677257bc26f4a6e22d": "1f8b08000000000000ff94924d8fdb2c1485d7f02bae2cbd919d3782fd48594d2b75914ca34c475d5f63eca0606030ee24b2fcdf2bfc91499ba61f0bb004c7f79c877b1d8a2356121ae9bf29212955b5b33e404a4922ac09f214124a92b20e09a5c4e590741ddbda62e765a94e7ddf75ec096bd9f71c9d8aca7bd7ca04e90d6a5ea08dba4a85439b33616b9e2bade2e2478fc136dc1d2b2eac29b9438d8532d1f95a5f598da6e2cedb60f3b6e42e9c9d6cb8ac5d382734a39473781e79662e46a3e6fd34f85604e8284101b09c7cd8161d25055a28d0b20f68693fd47a926f60e41be05c0dd014e06568bd61b46c8d8892b4987fcb206d603979ad407a1f97f559346c600d8be9aea384a0780058cc09be7cde6eba7e45498cf100c58a929e9258610db3e62b06714813744e2b814159c382ad75b28286a1c82819934de19ff1fc496a6da1f24e40216b0b31f194fb2a687691a6229c606a3e7b1cbf2bf0f215962e6783642f5f3348bd74fa0ccbe1e1d9c7b8ff4c3b2ad6f1f9d22b5946495907b6f3ca84324d0e43c0ff9a64701926e61ec6cb7e0379fd771c2ffbcdbfa2bc1f36ee1ecbe25a145b38d435e101269004febf708c0dbc856dbdfe3df04e990a5cdcc24182978d6d7d9ce35bdca8fc35a7fca13719a437adbaa04567585c5d777d9ca738d173fd6c4af6a86d23410cfb9fb20dda741cfca1d874407bfa3d0000ffff0c06c20f7a040000", "aaf0b28d854f8d677257bc26f4a6e22d": "1f8b08000000000000ff94924f6fe32c10c6cff0294696de08f25a70af94cbb62beda1cd46cd567b2678eca0da40314e1a59feee2b1cbbcdb6dbfd7300cbc3c3ccf363c62bfda82a8416c3c168a4d434de85088c924c3b1bf1396694646513334a89df41d6f7e2ce159b80a5791e86be176bd5e03048e54d527e746c6cc460552d0be592ae3271dfed84768ddc99daa4251f838aae95feb192dad9527a55abc2d854f9525fb95ad94afae0a2db75a5f4f1e4b195d8f878cade4a5d55a33c9a8019e5941e54804d700753608015a4b858e3718b91adf1989f039f8c2d98c523f33b71838ddb623860e039a4d8727b7e29ce39a552c2f43b3fa0a0c9cc6b34864e47e829511a603901893be529299483423971a31c1dc65c6b3ca61aa0e66ca06c01016317aca065677592b062bec681b5301bca419790348ce78021a4e5024fb55b58c16292f59410a5af0016b3996f5fef6efb21a72439ba8222a764a04497b082565cd7ae454a52be15cc37beaba8f72c53ded746ab689c15d1357596432b94e6949c2d4f545b75fa8275eda00a5e43818d1b6d4e401704fc45ca747c8669fcc4f5f99b43c02758fa9d1825f7f8c48105f4f5099663ebc5e7b4bf653f2b5663ef2e649c92b28962138c8d25cbf6a3c1ffda6cac32ceec47180ff7b7b06bfe8ee3e1fef65f515e83adff886571294a0d1df3da7805134806ffbf709cdbf91eb60bf5ef8137c656e0d316f708015bd78534e0ef7193f2d79cf8536f38b077ad7a414b95617171dc0f699ed2a8cff9f9e46c1c4ad0e3fe276fa396a51a03fd110000ffff1bbebd06ed040000",
"aeab2b2b2dab4699657654469ca5b02b": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a4cbe9389e09c124f7598a083cb9bdff21c6f96e45ebcb7fbb95109ab2ecedd3cc758ffd746b7125fc060000ffffe2756aadaa000000", "aeab2b2b2dab4699657654469ca5b02b": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a4cbe9389e09c124f7598a083cb9bdff21c6f96e45ebcb7fbb95109ab2ecedd3cc758ffd746b7125fc060000ffffe2756aadaa000000",
"b07da232bbd50bea80db83a2cb2ca45e": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000", "b07da232bbd50bea80db83a2cb2ca45e": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000",
"b0d155056e1d877b853104fa73d7dc20": "1f8b08000000000000ff5cccc10ac2300cc6f173f214230f505a058782275fc19b78084b0e81761d5dd4d7970ac2d8f1ff83ef7bdcb2e9ec4f84998b0ed781444b2584a555afbd7d5a0881455aaf7418430c31a44b3a1dc7332198e4be4b118127b7f73fc438dfad687df96fb812425396bd7d9ab9eeb19f6e2dae84df000000ffffd60a1b01ab000000",
"b3322d33b0e172c14cf0f1eab0a6b7da": "1f8b08000000000000ff4ccc41ca02310c05e075738ad2030c497f7e14c1955770272eca248bc0743a74a25e5fa22ebacbfb1e2fb7cba2b2da1dc25aaac4734c2cb525085b6fd63cdbbc250885b97ba27c9870c2894e99329137b3e9d397ff084179f19310026b59ae5aa53dec3344ac7b82d0a5f0c0f9c7afae2683ff7d3dc618fde7d01c714ff00e0000ffff7dc54fc8b7000000",
"b548f55cb04df40183977ace8191f981": "1f8b08000000000000ff248eb16eeb300c45e7f02b2e3249ef05d6de31f5da0e457e80b61959b52d1a120d0f45ffbdb03391e0bd073c21e07fb7a579c09e8aa4fc2dbd5108788c82d7dd3862e1492aea5604360aaa6d1d5245563b4b8694cfe09932cf2fae215ab99f380a0656a2b4ac5a0c8e2ed7986cdcbaa6d72544d5384b387e5fc9138510f52d4a96c226980a9b5698ea7cead173cb3db2ec0fa9d6b23a0ff76f60bde1089cbf414ad1e2f143979573eadd4135f7c3c765d9dba3fa297b7b3fc7970ca99edbc7bbf7f44b7f010000ffff3c96d9e80d010000",
"bd30b8e9f80b30f4e56dcd9e9552d779": "1f8b08000000000000ff4ccccf4ac0300c06f073fb14a587a120b3dd86caa02878f5e84d446a1b59b15d679afae7eda53a7497e4fb7e813cdcc6002b3d72e6cb2a8c909833cd6ddc90db4ef470d9ab5ef57ad6e3a82e4ecf5fd1522e4f1e52bea690205732ba7408d6dfffd70f0c0487be592c3fdd1056e86276e62e3b1b3bb7b40b994a2f57e9793a6b5b72661d857710460c8ab3e0638b7a8ffb5b61e4b448cede2ae0d79f093928958ae40c3ec11d78dc99d0ae079e7ef93b0000fffff662d40406010000",
"be4e113a73b0406a130eab40bc338032": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b4b03030325b04c49666e6a7e690948d2b058890b100000ffffb9f9177936000000",
"c20ee81720733a2f96a9b0df3a23a7a2": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000", "c20ee81720733a2f96a9b0df3a23a7a2": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000",
"c6edd0d1e59c8ee63811b57d99aa4f20": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"caf71f0f0cbb53c27c2bbcd00a648fd9": "1f8b08000000000000ff9452418bdb3c103d6b7ec57c860f2c486d7a0dcda194b69bc386b449ce65228f9d21b2642499ee62fcdf8b9c65d9c01eda838d34f39edf9b371ec85ca963ec491c80f4830f094b50456ba92b40153edede7594ce91cd97f81c0dd9e598a4e7024015d3543dfa661fb895a7799ea66a473dcf732d2e717064eb4632be937419cf95f17d7d162bf9a9af81928ff570ed6ae35d5b0f64a911f71770ebbb0234403b3ab34c506a9c4065ebd59e42e45283b2beabb64e52e9c46aac6b6cf83c7698416bcccd46c2661a285d66500db71c96ea17ebdff25b5f16af53614c1452a141bd78bd096850bf566832f1dbe8cc0a39045c6fb091a5ff79183244daa5fedf069dd86c570de4c4941c820635833299d3d3954b7321873e568725fa157ed4a06e6ba8763e49fb5c9a15be6ca33a6cbf3f9cf677f71fa7edf1ae70fcfaf3f1aeb0dd1d35a8d687c548ccca9f3e18506fa6ee3821e14d16ff8fc50a637548415c576a9d49bf25990bc6e50b8622ffb3833528a55e63cb19a97753e7275942572aff76d5c1320fe5edc8c6bb6669054e6370ef587938edb350c32d8d36adefb0730e7e863f010000ffffe9e8e3430d030000", "caf71f0f0cbb53c27c2bbcd00a648fd9": "1f8b08000000000000ff9452418bdb3c103d6b7ec57c860f2c486d7a0dcda194b69bc386b449ce65228f9d21b2642499ee62fcdf8b9c65d9c01eda838d34f39edf9b371ec85ca963ec491c80f4830f094b50456ba92b40153edede7594ce91cd97f81c0dd9e598a4e7024015d3543dfa661fb895a7799ea66a473dcf732d2e717064eb4632be937419cf95f17d7d162bf9a9af81928ff570ed6ae35d5b0f64a911f71770ebbb0234403b3ab34c506a9c4065ebd59e42e45283b2beabb64e52e9c46aac6b6cf83c7698416bcccd46c2661a285d66500db71c96ea17ebdff25b5f16af53614c1452a141bd78bd096850bf566832f1dbe8cc0a39045c6fb091a5ff79183244daa5fedf069dd86c570de4c4941c820635833299d3d3954b7321873e568725fa157ed4a06e6ba8763e49fb5c9a15be6ca33a6cbf3f9cf677f71fa7edf1ae70fcfaf3f1aeb0dd1d35a8d687c548ccca9f3e18506fa6ee3821e14d16ff8fc50a637548415c576a9d49bf25990bc6e50b8622ffb3833528a55e63cb19a97753e7275942572aff76d5c1320fe5edc8c6bb6669054e6370ef587938edb350c32d8d36adefb0730e7e863f010000ffffe9e8e3430d030000",
"cbfa81bf4d53c8a610fcbb7932ed95a3": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000", "cbfa81bf4d53c8a610fcbb7932ed95a3": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"cca1a28dc237a0b1a6d7768c4454036a": "1f8b08000000000000ff5491b18ed4301086ebcc530c96901294b3fb95b65836cd35b72be0057cde89b136f158ce8405a12be82829e841e231781dc4bd064abce874858b19ffff37e3dfc9bab3f58436050863e22c5843a51c47a18fa2a052fd280aa0523ec8fbf95e3b1ecd7d18c272cc395be1c9a4b33791c4e4e4ccc5e613c5e260f60369cf838d5e73f6c6e7e4143400c6e02ea5db0e35388e935cab2daa7787eeb0c15dd7e1ee78c4db4eade23bbaec87405130d205170cbab5867e8eeee9ba76bdc75765075d5a7b8e7df02d729209b5d68b5977c10e8724816383754723176d8b9433e7063f4355f8b8d9e215f76c48e169ad1ba89c5b7d8bb498567c7dcd50bfb6eeec33cff154372df6a3e8b72987287dad4e6172fc81f2a78d3127eaed3c887939a9b6c4d13450857e45bfd8620cc3b2569549e61c97729d0ad503fcefddd1e5e92db5734dbbc8e0618df0f1fb8fbf5fbfa17f73dce39fdfbf1e7f7e01633c6f3c45ca5608cb67a2300f98320b3bbcb959a3b629e8b503ff020000ffffb1117d162f020000", "cca1a28dc237a0b1a6d7768c4454036a": "1f8b08000000000000ff5491b18ed4301086ebcc530c96901294b3fb95b65836cd35b72be0057cde89b136f158ce8405a12be82829e841e231781dc4bd064abce874858b19ffff37e3dfc9bab3f58436050863e22c5843a51c47a18fa2a052fd280aa0523ec8fbf95e3b1ecd7d18c272cc395be1c9a4b33791c4e4e4ccc5e613c5e260f60369cf838d5e73f6c6e7e4143400c6e02ea5db0e35388e935cab2daa7787eeb0c15dd7e1ee78c4db4eade23bbaec87405130d205170cbab5867e8eeee9ba76bdc75765075d5a7b8e7df02d729209b5d68b5977c10e8724816383754723176d8b9433e7063f4355f8b8d9e215f76c48e169ad1ba89c5b7d8bb498567c7dcd50bfb6eeec33cff154372df6a3e8b72987287dad4e6172fc81f2a78d3127eaed3c887939a9b6c4d13450857e45bfd8620cc3b2569549e61c97729d0ad503fcefddd1e5e92db5734dbbc8e0618df0f1fb8fbf5fbfa17f73dce39fdfbf1e7f7e01633c6f3c45ca5608cb67a2300f98320b3bbcb959a3b629e8b503ff020000ffffb1117d162f020000",
"cdc9702cf3b30ddc315510a28df1ff83": "1f8b08000000000000ff8c535b6b1b3b107e5efd8a3982046d70b4e7e1701e5cfc10dc10426b3790b62fa504453bab08ebb2c8e3c4c6ec7f2f922f4dd2d2e66159edf25de69b19f54a2f9441685564ccfa3e2602c12aae63205c136715ef3c71c62abeddca596c6f1276763d0cdbad9c2b8fc3d0d8409882728d8f2dbacc30961e56f75247dfdc5b67f3d32c92a2b86cfa8569b4d20fd878f4e5f016420c5dd32ba75a1bde0077d1705633d634268e0d064c8a107600a0181d180c5e33daf408775e4349d0298db06555d380d763385fe066b2c0cd452238cfc8894162d534977c91c86a8742c3be4d72ba7b8fc0b659edffff6a1067a51f720f1e01a61453fd7b035cf736e1a4952dfa78593e5875d1b66fb51b814a042f1d6b1098d21f6c59f51e1dd241bf78fd25d333c181b16e1534ccf16936153508afe1ec305439db1f4aec3d2577f75125d09d8125a595a6fca79a3a8b819e71a73174d6b06a6095ed0a7f02fbe9cb2b24c18f488adef15a7e095ea5e583729f3fcd3e8a53dd99fa5de1fd3381605d714948ab148aa8d73001388accf149e8cec85d1d353b400f01450b67ad8a35dcd8606653a169fdba472f3a93ed8e75b7d26b798b945923383d9a5e13faed07dc8c81f736183e82afcaad700cdfbedf6f0805ef6330bc1e41590645368631fc3bfc9acb45232fb3afc8773614af9bebf955bdab469c3cd6bc0ca12ed95f65db2d82f839e125251b4c56de21a1f3246ffb64037582ab4477272dcf2b9117e047000000ffffe48ced133d040000", "cdc9702cf3b30ddc315510a28df1ff83": "1f8b08000000000000ff8c544d6bdb40103d6b7fc57421613738520fa507171f821b4268ed06d2f6524ad8ac469bc5fb21d6e3c4c6e8bf97956ce7a325cd416825cd7b6fe6cd43add20b65106a1519b3be8d8940b082eb1808d7c459c11b4f9cb1826fb7e52cd657091bbbeebaedb69c2b8f5d57d940988272958f35ba8c3096ee56b7a58ebebab5cee6ab5a24457159b50b5369a5efb0f2e8fbc35b00313455ab9caa6d7843b98b8633c9585599383618302942180a806274603078cd68d322dc780dfd048dd2085b565415783d86d3056e260bdc9c2582d35c393148ac98e696cf1259ed5068d8d9544e87fb086c9dd93e7e90204e7a3fca5df10830a598e4bf0570ddda8493baacd1c7f3fe81156775fd56b911a844f05c5182c0945e9165c56774487bfe5eeb3f333d21ec186b5641c31c1f66532141780d27fba596b3dd6104ba815c2764efc00e9d8dbe572947add08d81036e1a43634d7e4bb0db78f9fddbec2b2b242b6cd3534c0e5f2e90043f60297ac765f92378959677ca89634df2530f793781605d562d12d22a0556744ff8340d54536731d0538eac2d8e75635e25f21a26f038c41c1f060c2b740393ddfcb0f5ba9cbab844213bb687ef6d14359cd42a4ab8b2c1cca642d3fae5269ef99f5b38f45f975e97d748193582e3432397847efb053763e0ad0d868fe0a7722b1cc3afdfb71b42c1db180c9723e823a7c8c63086f7dddfb3ba68caf3ac2bf29f21f45a5797f30b3974238eee25eff72b7b3f5ecc36c44d3ce66849c9069399874a683c95d76db2811ac155a29ba39ae7e0e598fd090000ffff9a984c0da3040000",
"d1ce3e717c8a1e9830e9e1626ff88fa8": "1f8b08000000000000ff8c53dd6ef3360cbd969e82358ac00e1209dd865d78f0c5d66c4381b52bf6735dc812ed0891255796d71481df7d90ecf46718be2f01624914299e7348f6421e448ba084a35477bdf301724a32e96cc063c828c982ee30a39464a713bb77ead163a38fd3743ab107d1e134716d037a2b0cef9c4213435a1df663cda4eb78ad8d8e7f7ef022b881f787964b21f7c83becd2e6e2008f4a0f97783bdbf05e18a1b4bdc05d89206a31201f9e2f013fbc5ac97bdda3d1167923ac1ba34cc728137c2d78d6b2a094f3d6952d5af42220cc1e109c33d0a2adc34039879d70b12e90f46d84441a5e7b4ce637139c28b9356ec0bca0e451db3697e1084bf5d8edbc1690a3f780de3b5f50c239d46128616b476392b4d52a958efde88396064f77bb727b33c156ee511e9ea2db93740aabebabca6ab35a5db3bb5d556d6f28592272f9df9c1bd02ac2fcfebb02f2f5a7e737672453d4215154c2b1995d3c0dc18f32446aaa86b7df7a78366cf71325a90fcec674607fc42f259dfce07eee2f76bf6c28490bace7a2b15fd24289c2cefd7cecb5c708f8db6f165c0ff802165f40244cc22af018466f196d462be375ee3fe5df4027ff27ed06547d065f40ae620193048b0c91e73fc2836cda85f98912b27b07955a8bed462f827696928912dda4072a58da9cfd8a21cf44df1b2d93170bae3359c1feb69df0c35e98bf7ebfff2d5fc9a62d7e48a15715586d626e32d34aef2aa860a5848b665597a0ea4d72507a28c1c77d274be864dc2572252c624639b2799e8b78fb2e6a39ab9a7f6291cba665ef1c0be090eeff44e9ac8a2f4cf40c6c2e47ea7290e91bf6081e07377a894b3972056b255c01cb34a4ee619d646fd3a1d85cab0f06557f3ccd653b1be6ac71a4a08f9f2fe5bc68f022a29951549e4ef4df000000ffff20759cb67c050000", "d1ce3e717c8a1e9830e9e1626ff88fa8": "1f8b08000000000000ff9c545d8be336147d967ec55db3047bc8486c5bfae0e287eeb82d0b9d74e8b6cf8b2c5d3b22b2e495e54d96e0ff5e243bf351ca346c20967c75753fce39d7839007d12128e128d5fde07c809c924c3a1bf014324ab2a07bcc2825d9f9ccee9d7af0d8ead33c9fcf6c277a9c67ae6d406f85e1bd5368e2954e87fdd430e97ade68a3e39f1fbc086ee4c3a1e352c83df21efbb4b9fa8247a5c76bbc9d6df9208c50da5ee1ae44108d18918f9faf297efc6a251ff480465be4adb06e8a309d224cf07f971fb17ce6d739d719e447ed31a305a55f848707efbe68851e2a8876b6c3e3470cf90e8f5bd8e1b17e9f963f232069777f5750ca79e7ca0e2d7a111096ac109c33d0a16dc24839875ab8c83524ce5a219186af0326f3a309ce94dc1937625e50f2a06d97cb70825511ec6e590bc8d17b40ef9d2f28e11c9a3096706b2763125dd526c981fdec839606cf1feaf2f6dd0cb7728ff2f029ba7d924e61f5f64d65b5d96cdeb20f7555ddbea364bd91cb7fe7dc8256b1cc1f7f2820bf79117e7ba9648e38a41695706ce92ebe8dc14f32c4d654038fbf9bf1b361f57b4a92b62ec6f4c212ba94f4f299fb45b3ec7edd509216b85984c07e4d0b250a7bf7cb69d01e63c1df7fb7d6b5c323583c82483509abc06398bc65b49dac8cc7b97f917f0bbdfc8fb45b50cda5f802721509dc826c2186c98b84c68a486c79491233d7c2e53e068d11125a29f1e5e49b72dfa85793473dcbb65b19385342ea2770d2d8b07af2226867299929d16d0a50c13ac2ec370c792686c16899bc5870bdc90af6b7ed851ff7c2fcf5c7fdeff946b65df153bafaa602ab4dccbd769ee22aa860a3848b66d594a09a6d72507a2cc1c77d2fcb880c250ba925aca4465ab2e55b55c4d32772cb85ddfc4517b96c3bf6d463011cd2f94794ceaa1861a644b650816269ce2e04ad22493690e919f6081e47377989ab4856c40b586734699a2d1c5dc6760914671786f8782dcc5513fe5c45dad099fe130000ffffba9a548b39060000",
"d34aa8c5fcb453998edcaa9594393f70": "1f8b08000000000000ff8c535b6b1b3b107e5efd8a3982046d70b4e7e1701e5cfc10dc10426b3790b62fa504453bab08ebb2c8e3c4c6ec7f2f922f4dd2d2e66159edf25de69b19f54a2f9441685564ccfa3e2602c12aae63205c136715ef3c71c62abeddca596c6f1276763d0cdbad9c2b8fc3d0d8409882728d8f2dbacc30961e56f75247dfdc5b67f3d32c92a2b86cfa8569b4d20fd878f4e5f016420c5dd32ba75a1bde0077d1705633d634268e0d064c8a107600a0181d180c5e33daf408775e4349d0298db06555d380d763385fe066b2c0cd452238cfc8894162d534977c91c86a8742c3be4d72ba7b8fc0b659edffff6a1067a51f720f1e01a61453fd7b035cf736e1a4952dfa78593e5875d1b66fb51b814a042f1d6b1098d21f6c59f51e1dd241bf78fd25d333c181b16e1534ccf16936153508afe1ec305439db1f4aec3d2577f75125d09d8125a595a6fca79a3a8b819e71a73174d6b06a6095ed0a7f02fbe9cb2b24c18f488adef15a7e095ea5e583729f3fcd3e8a53dd99fa5de1fd3381605d714948ab148aa8d73001388accf149e8cec85d1d353b400f01450b67ad8a35dcd8606653a169fdba472f3a93ed8e75b7d26b798b945923383d9a5e13faed07dc8c81f736183e82afcaad700cdfbedf6f0805ef6330bc1e41590645368631fc3bfc9acb45232fb3afc8773614af9bebf955bdab469c3cd6bc0ca12ed95f65db2d82f839e125251b4c56de21a1f3246ffb64037582ab4477272dcf2b9117e047000000ffffe48ced133d040000", "d34aa8c5fcb453998edcaa9594393f70": "1f8b08000000000000ff8c544d6bdb40103d6b7fc57421613738520fa507171f821b4268ed06d2f6524ad8ac469bc5fb21d6e3c4c6e8bf97956ce7a325cd416825cd7b6fe6cd43add20b65106a1519b3be8d8940b082eb1808d7c459c11b4f9cb1826fb7e52cd657091bbbeebaedb69c2b8f5d57d940988272958f35ba8c3096ee56b7a58ebebab5cee6ab5a24457159b50b5369a5efb0f2e8fbc35b00313455ab9caa6d7843b98b8633c9585599383618302942180a806274603078cd68d322dc780dfd048dd2085b565415783d86d3056e260bdc9c2582d35c393148ac98e696cf1259ed5068d8d9544e87fb086c9dd93e7e90204e7a3fca5df10830a598e4bf0570ddda8493baacd1c7f3fe81156775fd56b911a844f05c5182c0945e9165c56774487bfe5eeb3f333d21ec186b5641c31c1f66532141780d27fba596b3dd6104ba815c2764efc00e9d8dbe572947add08d81036e1a43634d7e4bb0db78f9fddbec2b2b242b6cd3534c0e5f2e90043f60297ac765f92378959677ca89634df2530f793781605d562d12d22a0556744ff8340d54536731d0538eac2d8e75635e25f21a26f038c41c1f060c2b740393ddfcb0f5ba9cbab844213bb687ef6d14359cd42a4ab8b2c1cca642d3fae5269ef99f5b38f45f975e97d748193582e3432397847efb053763e0ad0d868fe0a7722b1cc3afdfb71b42c1db180c9723e823a7c8c63086f7dddfb3ba68caf3ac2bf29f21f45a5797f30b3974238eee25eff72b7b3f5ecc36c44d3ce66849c9069399874a683c95d76db2811ac155a29ba39ae7e0e598fd090000ffff9a984c0da3040000",
"d3a9bc220c8ae2d4e01680157e65d694": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000", "d3a9bc220c8ae2d4e01680157e65d694": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"d5f9b4870ad447f7ef808033db2803ad": "1f8b08000000000000ff94924d8fdb2c1485d7f02bae2cbd919d3782fd48594d2b75914ca34c475d5f63eca0606030ee24b2fcdf2bfc91499ba61f0bb004c7f79c877b1d8a2356121ae9bf29212955b5b33e404a4922ac09f214124a92b20e09a5c4e590741ddbda62e765a94e7ddf75ec096bd9f71c9d8aca7bd7ca04e90d6a5ea08dba4a85439b33616b9e2bade2e2478fc136dc1d2b2eac29b9438d8532d1f95a5f598da6e2cedb60f3b6e42e9c9d6cb8ac5d382734a39473781e79662e46a3e6fd34f85604e8284101b09c7cd8161d25055a28d0b20f68693fd47a926f60e41be05c0dd014e06568bd61b46c8d8892b4987fcb206d603979ad407a1f97f559346c600d8be9aea384a0780058cc09be7cde6eba7e45498cf100c58a929e9258610db3e62b06714813744e2b814159c382ad75b28286a1c82819934de19ff1fc496a6da1f24e40216b0b31f194fb2a687691a6229c606a3e7b1cbf2bf0f215962e6783642f5f3348bd74fa0ccbe1e1d9c7b8ff4c3b2ad6f1f9d22b5946495907b6f3ca84324d0e43c0ff9a64701926e61ec6cb7e0379fd771c2ffbcdbfa2bc1f36ee1ecbe25a145b38d435e101269004febf708c0dbc856dbdfe3df04e990a5cdcc24182978d6d7d9ce35bdca8fc35a7fca13719a437adbaa04567585c5d777d9ca738d173fd6c4af6a86d23410cfb9fb20dda741cfca1d874407bfa3d0000ffff0c06c20f7a040000", "d3c2a7dd82dae9f20e2fc67b98fb3a9e": "1f8b08000000000000ff4ccccf4ac0300c06f073fb14a587a120b3dd86caa02878f5e84d446a1b59b15d679afae7eda53a7497e4fb7e813cdcc6002b3d72e6cb2a8c909833cd6ddc90db4ef470d9ab5ef57ad6e3a82e4ecf5fd1522e4f1e52bea690205732ba7408d6dfffd70f0c0487be592c3fdd1056e86276e62e3b1b3bb7b40b994a2f57e9793a6b5b72661d857710460c8ab3e0638b7a8ffb5b61e4b448cede2ae0d79f093928958ae40c3ec11d78dc99d0ae079e7ef93b0000fffff662d40406010000",
"d81923e98881c369f957c7d15decf26f": "1f8b08000000000000ff8c91cd6ae33010c7cfd653cc0a769182911f60c9291bc2c26e1a9af45c14595244648d91e53450f2ee45b25328bde42004c3ffe3374c2fd5595a0dad44425cd7634cc048451586a4af89125251ebd2693c0a855d7374dee5d79ca34c3834fdd9364aaa936ea26edd401f5063304d2fbd6c5d7840eed152c209316350b0d56fcfb98671601116a55294490d3ac6fc30727827d5454650c6c290e2a8529e542bef744877d70a8371965437523953cc4b98a9c44627462759c2ce532e5e4227e37092fef0f4ff1ffba58ce5bf8be9c71282f3253fea34c6501273d8e4ff2456c68a898093bbf436afc55a58b41239ec5cb0b33c5d613e4146cd3f07f6754767e0b59ed15b31f5fdc16cad81eed7075a03ed5db0e5c760e977668f56ac7320cb070f62af13dbfddd6ef854c37e5e382d157cda6be6fe080000ffffb73c6a1735020000", "d5f9b4870ad447f7ef808033db2803ad": "1f8b08000000000000ff94924f6fe32c10c6cff0294696de08f25a70af94cbb62beda1cd46cd567b2678eca0da40314e1a59feee2b1cbbcdb6dbfd7300cbc3c3ccf363c62bfda82a8416c3c168a4d434de85088c924c3b1bf1396694646513334a89df41d6f7e2ce159b80a5791e86be176bd5e03048e54d527e746c6cc460552d0be592ae3271dfed84768ddc99daa4251f838aae95feb192dad9527a55abc2d854f9525fb95ad94afae0a2db75a5f4f1e4b195d8f878cade4a5d55a33c9a8019e5941e54804d700753608015a4b858e3718b91adf1989f039f8c2d98c523f33b71838ddb623860e039a4d8727b7e29ce39a552c2f43b3fa0a0c9cc6b34864e47e829511a603901893be529299483423971a31c1dc65c6b3ca61aa0e66ca06c01016317aca065677592b062bec681b5301bca419790348ce78021a4e5024fb55b58c16292f59410a5af0016b3996f5fef6efb21a72439ba8222a764a04497b082565cd7ae454a52be15cc37beaba8f72c53ded746ab689c15d1357596432b94e6949c2d4f545b75fa8275eda00a5e43818d1b6d4e401704fc45ca747c8669fcc4f5f99b43c02758fa9d1825f7f8c48105f4f5099663ebc5e7b4bf653f2b5663ef2e649c92b28962138c8d25cbf6a3c1ffda6cac32ceec47180ff7b7b06bfe8ee3e1fef65f515e83adff886571294a0d1df3da7805134806ffbf709cdbf91eb60bf5ef8137c656e0d316f708015bd78534e0ef7193f2d79cf8536f38b077ad7a414b95617171dc0f699ed2a8cff9f9e46c1c4ad0e3fe276fa396a51a03fd110000ffff1bbebd06ed040000",
"de469d397e894ad53241ccaa67354d77": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2d02040000ffff7187321713000000", "d81923e98881c369f957c7d15decf26f": "1f8b08000000000000ff8c52df8a2a2118bfd6a7f88e704263701ee0d05527e2c0a98dadbd5ecc51931c1d1c6b83e8dd17c7215a16962e44f8e6fbfd1d3b218fc2286844c0d8b65d8809284644069fd425118c1131361d4e7b2e435befadb3f9d4c72852e8ebee686a29e441d55135b6274f6c07afeb4e38d158ffc4ba0b866086b13e79096bf5f19a6528031a613a48f2615281d4907728ab40c5984f880cae189d45cc8990d4060a621ebcb6268f128c4ef84a7418318cac1ee0b3fb87a54a94145c0aad238cbff956c4fe201c9dc8c4fe0cfbbf66e0adcb7228aa748a1ea3db03994c8567eeacf2e99163f7b2fa4f27529b1f893247f170af60c0602435ccc6e0d7c8e72ef48ab28c28e0dbd81c6d60da88c06063bd2904325d60fccbb9917c33a05fbbb31adeab3143c38b83bf21432b20dbc58e54403aebcd70076fc8f7142e18bec88434bf29cfb72ad1cdbff5921519fafbccc820c14ad2d1f767000000ffff7e2fc7cb98020000",
"e507552ddfbcbf9862edb00a6a06942e": "1f8b08000000000000ff8c53dd6ef3360cbd969e82358ac00e1209dd865d78f0c5d66c4381b52bf6735dc812ed0891255796d71481df7d90ecf46718be2f01624914299e7348f6421e448ba084a35477bdf301724a32e96cc063c828c982ee30a39464a713bb77ead163a38fd3743ab107d1e134716d037a2b0cef9c4213435a1df663cda4eb78ad8d8e7f7ef022b881f787964b21f7c83becd2e6e2008f4a0f97783bdbf05e18a1b4bdc05d89206a31201f9e2f013fbc5ac97bdda3d1167923ac1ba34cc728137c2d78d6b2a094f3d6952d5af42220cc1e109c33d0a2adc34039879d70b12e90f46d84441a5e7b4ce637139c28b9356ec0bca0e451db3697e1084bf5d8edbc1690a3f780de3b5f50c239d46128616b476392b4d52a958efde88396064f77bb727b33c156ee511e9ea2db93740aabebabca6ab35a5db3bb5d556d6f28592272f9df9c1bd02ac2fcfebb02f2f5a7e737672453d4215154c2b1995d3c0dc18f32446aaa86b7df7a78366cf71325a90fcec674607fc42f259dfce07eee2f76bf6c28490bace7a2b15fd24289c2cefd7cecb5c708f8db6f165c0ff802165f40244cc22af018466f196d462be375ee3fe5df4027ff27ed06547d065f40ae620193048b0c91e73fc2836cda85f98912b27b07955a8bed462f827696928912dda4072a58da9cfd8a21cf44df1b2d93170bae3359c1feb69df0c35e98bf7ebfff2d5fc9a62d7e48a15715586d626e32d34aef2aa860a5848b665597a0ea4d72507a28c1c77d274be864dc2572252c624639b2799e8b78fb2e6a39ab9a7f6291cba665ef1c0be090eeff44e9ac8a2f4cf40c6c2e47ea7290e91bf6081e07377a894b3972056b255c01cb34a4ee619d646fd3a1d85cab0f06557f3ccd653b1be6ac71a4a08f9f2fe5bc68f022a29951549e4ef4df000000ffff20759cb67c050000", "de469d397e894ad53241ccaa67354d77": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2de202040000ffffbe75c21514000000",
"ee89e1856fc911f261533efa462e6867": "1f8b08000000000000ff8c90cd8adb3010c7cfd6534c75285258a44be9a5e4d0dd855e36e9f7038cf515115972e4719362fceec58e0ba5a73d0c0231bff97ff468ce181c582c8cc5ae2f9540b0869b92c9dd8833d6f069528762bf54e7e36d9ea7491db173f3ac6326573326dd15eb12670d0f914e63ab4ce9741b535c469f2b5219747f0eda94ec758f096dccaf58b748d8e2e0f470499c49c6fc980d1cddf5f9514810b685dd7049eaf9f1015cadcb942a6162cd2fac607c8081ea6868f9699e527499eec053c93e06d6ccac897e45f7b0b9529f1c096e5b45a54b5caa9fb9c33a9c30fdf87c78116f8d0ff2c34abcd9438e693d5d1d8d35afe76c0b7b58248eee7af8fdfdeb8b303ea8bbb6647f37e72d89b0b0b358247cc3ebc74ad124270cdd60eb7ef1b9bc0f102dc44cefdf49105809766bdf6a43fe0faf350447b09407be960e6cfb8ff29f000000ffffed2515fbf0010000", "e3d7243f3d9352173a54efb3a26c1d3d": "1f8b08000000000000ff248eb16eeb300c45e7f02b2e3249ef05d6de31f5da0e457e80b61959b52d1a120d0f45ffbdb03391e0bd073c21e07fb7a579c09e8aa4fc2dbd5108788c82d7dd3862e1492aea5604360aaa6d1d5245563b4b8694cfe09932cf2fae215ab99f380a0656a2b4ac5a0c8e2ed7986cdcbaa6d72544d5384b387e5fc9138510f52d4a96c226980a9b5698ea7cead173cb3db2ec0fa9d6b23a0ff76f60bde1089cbf414ad1e2f143979573eadd4135f7c3c765d9dba3fa297b7b3fc7970ca99edbc7bbf7f44b7f010000ffff3c96d9e80d010000",
"e3f75655d10714df86daec6cb01335fb": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"e507552ddfbcbf9862edb00a6a06942e": "1f8b08000000000000ff9c545d8be336147d967ec55db3047bc8486c5bfae0e287eeb82d0b9d74e8b6cf8b2c5d3b22b2e495e54d96e0ff5e243bf351ca346c20967c75753fce39d7839007d12128e128d5fde07c809c924c3a1bf014324ab2a07bcc2825d9f9ccee9d7af0d8ead33c9fcf6c277a9c67ae6d406f85e1bd5368e2954e87fdd430e97ade68a3e39f1fbc086ee4c3a1e352c83df21efbb4b9fa8247a5c76bbc9d6df9208c50da5ee1ae44108d18918f9faf297efc6a251ff480465be4adb06e8a309d224cf07f971fb17ce6d739d719e447ed31a305a55f848707efbe68851e2a8876b6c3e3470cf90e8f5bd8e1b17e9f963f232069777f5750ca79e7ca0e2d7a111096ac109c33d0a16dc24839875ab8c83524ce5a219186af0326f3a309ce94dc1937625e50f2a06d97cb70825511ec6e590bc8d17b40ef9d2f28e11c9a3096706b2763125dd526c981fdec839606cf1feaf2f6dd0cb7728ff2f029ba7d924e61f5f64d65b5d96cdeb20f7555ddbea364bd91cb7fe7dc8256b1cc1f7f2820bf79117e7ba9648e38a41695706ce92ebe8dc14f32c4d654038fbf9bf1b361f57b4a92b62ec6f4c212ba94f4f299fb45b3ec7edd509216b85984c07e4d0b250a7bf7cb69d01e63c1df7fb7d6b5c323583c82483509abc06398bc65b49dac8cc7b97f917f0bbdfc8fb45b50cda5f802721509dc826c2186c98b84c68a486c79491233d7c2e53e068d11125a29f1e5e49b72dfa85793473dcbb65b19385342ea2770d2d8b07af2226867299929d16d0a50c13ac2ec370c792686c16899bc5870bdc90af6b7ed851ff7c2fcf5c7fdeff946b65df153bafaa602ab4dccbd769ee22aa860a3848b66d594a09a6d72507a2cc1c77d2fcb880c250ba925aca4465ab2e55b55c4d32772cb85ddfc4517b96c3bf6d463011cd2f94794ceaa1861a644b650816269ce2e04ad22493690e919f6081e47377989ab4856c40b586734699a2d1c5dc6760914671786f8782dcc5513fe5c45dad099fe130000ffffba9a548b39060000",
"ee89e1856fc911f261533efa462e6867": "1f8b08000000000000ff8c51cb8a1b31103c4b5fd199c32219235d422ec187ac1772899df707b45eb3c21ac9d6b4638761fe3dc899049343d8432350775575571dd11eb0f7e0b0701e8763a90482b3ce964cfe4a1de7ac9b26b52bee53f5215ee7799ad41e073fcf3a66f23563d243713e759c757da4e7b351b60cdac4145be943452aa33e1e7a6d4b0efa88095dcc2f1877486870f47a3ca58e4bcec3395bd8fbcbd3a390209c81d5784aeae9710d36406b0ab9065f6bab52254c9cfdc0daee6136f4d086b72587d8b70f826513f5ede3ee036792b3186ee8cddfce7b4fa2734651195227d5f73c601d9f3189074bf2ed6df8d506724c4d8a554fe79a399bef982cfd26d9a6e833dd733455f16043ff5f226760735b7cef2fbb9f5f3f2f10ce6c80cd72334ccea86d2aa31772e67fd0f3e29770b07258247cc1cbbb4ad1262f2c5d6149b839d2de35440731d39bd712045682d52d55b540fef5556be83d418b08422d033873a7fc2b0000ffff866476e156020000",
"f14888b9e73b4709f9f661ca025578a5": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000", "f14888b9e73b4709f9f661ca025578a5": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000",
"f6819875960d317b08fedcef244fc640": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000", "f6819875960d317b08fedcef244fc640": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000",
"f6e84ad3fd70355fca59f33e23639704": "1f8b08000000000000ff5ccdc14ec3300cc6f1f3fc143ec2614e9c32525e827748db6022927964c98434f5dd51e15238f862fdfefa8a2e3d47bcdfe93594b8ae00a2c8c40ea0c6cf9e6ac407404494d4defb44b31633a59cb6331f3534bd6209d7162b1c764454d45caa369dfa1bde981cf13f90c359fe90811c1c7effa455cc9739c786374b96ecd1597eb1cf6ee4f1343c9d8e4be0c1cf7ef4bcf82d52c99176add4cbfc33ebc8c2237c070000ffff34bdd5b6e6000000", "f6e84ad3fd70355fca59f33e23639704": "1f8b08000000000000ff5ccd414e03310c85e1353e8597b0a81327940c97e00e9999602292baa4498554f5eea88505edc22b7fbf5ed5759484a713bdc59ace67005164620fd0d2d7c82de12320224aee1f63a645ab9973c997339f2d763d608d879edabd121535fba65de7f18e4726477c310f37a6c49ddc284fee575d5fa44dccb7d9a58e474b96ecc6597eb52f6ee269eb9fb79b35b20f4b9802afe1af532989fee5d2f6cb75df918527809f000000ffff3ae05435f3000000",
"f82400a3d4ac022882197ca12a896f1b": "1f8b08000000000000ff9c90314bc3401cc5f77c8aff96045c0ae2521c62724a30b994f46ee8943bd3030f1b2bc9298e6eba281d8a1d74d04941280e226a07bf4c9bda6f21676b23bab9dc71efeefddebd7f9a0bae04b4b9e23bbc10b09773d52d92b6c8ba75e3f0b760b831720802e26c040818cf954c3ba2606019004cb619c87d65d56a3650dcf4b730f2004704300d02702889121fbb310a1126e046e1d76e8e5f46b3fed0f7cc15cd5052750483239ea7bb3cb7d656ed8ab0b44c7ae7d3bbc7b9215332130cf45a289e1d54cf3db4e9d080804be3186192103f444de2840d8830d086a78bfcbd5b8694d72793dec5f87d58f65fcbc1f36cf0340f4cff1158fdfcec6a327afb816bc47ee8c42dd8462db0f4046dadea1393c7c9a29cb568691bf6376add2c2f4fa70f371fb7f766ddf80c0000ffff632acdfbc6010000",
"faef00ce61dfdd11dc5b0198e8cb4d24": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b0b03030325b04c49666e6a7e690948d2b058890b100000ffffb7699cdc36000000", "faef00ce61dfdd11dc5b0198e8cb4d24": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b0b03030325b04c49666e6a7e690948d2b058890b100000ffffb7699cdc36000000",
"fc66ed973976512794d4a2930aa4060d": "1f8b08000000000000ff4ccc41ca02310c05e075738ad2030c497f7e14c1955770272eca248bc0743a74a25e5fa22ebacbfb1e2fb7cba2b2da1dc25aaac4734c2cb525085b6fd63cdbbc250885b97ba27c9870c2894e99329137b3e9d397ff084179f19310026b59ae5aa53dec3344ac7b82d0a5f0c0f9c7afae2683ff7d3dc618fde7d01c714ff00e0000ffff7dc54fc8b7000000",
"fe2a9fe5f84f01e208243862890c2182": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000", "fe2a9fe5f84f01e208243862890c2182": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000",
}) })
if err != nil { if err != nil {
@ -104,16 +132,26 @@ var _ = func() error {
b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "aeab2b2b2dab4699657654469ca5b02b"}) b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "aeab2b2b2dab4699657654469ca5b02b"})
b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "95d28ebee82ae43dfc0c8b16b6088b2d"}) b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "95d28ebee82ae43dfc0c8b16b6088b2d"})
b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "a416686e4cfcf5ed8366cfcf264e48e0"}) b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "a416686e4cfcf5ed8366cfcf264e48e0"})
b.SetResolver("internal/dao/dao_test.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "5fbeeedba452fb00cc08114c465ccc6f"})
b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "ee89e1856fc911f261533efa462e6867"}) b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "ee89e1856fc911f261533efa462e6867"})
b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d34aa8c5fcb453998edcaa9594393f70"}) b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d34aa8c5fcb453998edcaa9594393f70"})
b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "89e787ea2b6d77d3061b5e56a50c6e36"}) b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "89e787ea2b6d77d3061b5e56a50c6e36"})
b.SetResolver("internal/dao/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "213aa9a2a3ab9063ff31669f2b262397"})
b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "97e4f2cf9f4ad4fc842f20a7fb124f91"}) b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "97e4f2cf9f4ad4fc842f20a7fb124f91"})
b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "348f254eb8f48eaf3d0330c83c18324c"}) b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "348f254eb8f48eaf3d0330c83c18324c"})
b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "b07da232bbd50bea80db83a2cb2ca45e"}) b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "b07da232bbd50bea80db83a2cb2ca45e"})
b.SetResolver("internal/server/grpc/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "984dd6df0bfb1684d6d188b40962ca7b"}) b.SetResolver("internal/server/grpc/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "984dd6df0bfb1684d6d188b40962ca7b"})
b.SetResolver("internal/server/http/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "468e50d126ac1e7c1a9ea44dde207990"}) b.SetResolver("internal/server/http/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "468e50d126ac1e7c1a9ea44dde207990"})
b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "aaf0b28d854f8d677257bc26f4a6e22d"}) b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "aaf0b28d854f8d677257bc26f4a6e22d"})
b.SetResolver("test/0_db.sql", packr.Pointer{ForwardBox: gk, ForwardPath: "f82400a3d4ac022882197ca12a896f1b"})
b.SetResolver("test/1_data.sql", packr.Pointer{ForwardBox: gk, ForwardPath: "6a0765f64b1e9febbe82b717286415c5"})
b.SetResolver("test/application.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "8a7d67b864f45201854ef2ad00b51b09"})
b.SetResolver("test/db.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "bd30b8e9f80b30f4e56dcd9e9552d779"})
b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "5d243c2aa906cb9527df41e508cda83d"}) b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "5d243c2aa906cb9527df41e508cda83d"})
b.SetResolver("test/grpc.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "be4e113a73b0406a130eab40bc338032"})
b.SetResolver("test/http.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "157b33c7997882e0620862106b4b53c7"})
b.SetResolver("test/memcache.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "b3322d33b0e172c14cf0f1eab0a6b7da"})
b.SetResolver("test/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "47fecc198864e8c30abf93f8cf34c7cf"})
}() }()
@ -132,15 +170,24 @@ var _ = func() error {
b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "aaa0e84aef1077c2699e21ba05d51c7f"}) b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "aaa0e84aef1077c2699e21ba05d51c7f"})
b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "48e53a59007a8dda61d904d989943a09"}) b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "48e53a59007a8dda61d904d989943a09"})
b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "e507552ddfbcbf9862edb00a6a06942e"}) b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "e507552ddfbcbf9862edb00a6a06942e"})
b.SetResolver("internal/dao/dao_test.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "10621fa6dab19977ebee067a93861c10"})
b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "6640f2771831eddce9f1132a8ffa02b1"}) b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "6640f2771831eddce9f1132a8ffa02b1"})
b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "1794b30bcdd9584d5877963a3cb28504"}) b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "1794b30bcdd9584d5877963a3cb28504"})
b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d81923e98881c369f957c7d15decf26f"}) b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d81923e98881c369f957c7d15decf26f"})
b.SetResolver("internal/dao/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "e3d7243f3d9352173a54efb3a26c1d3d"})
b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "2f762fe51f2becdb8677b17926a52f03"}) b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "2f762fe51f2becdb8677b17926a52f03"})
b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "80a49866e2154ebe00c57fd7c80a4cab"}) b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "80a49866e2154ebe00c57fd7c80a4cab"})
b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "c20ee81720733a2f96a9b0df3a23a7a2"}) b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "c20ee81720733a2f96a9b0df3a23a7a2"})
b.SetResolver("internal/server/grpc/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "65c9c5ceead4379a32ef56fe8044a9a7"}) b.SetResolver("internal/server/grpc/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "65c9c5ceead4379a32ef56fe8044a9a7"})
b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "532d363951d4f0d0c18e620c67cb7b40"}) b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "532d363951d4f0d0c18e620c67cb7b40"})
b.SetResolver("test/0_db.sql", packr.Pointer{ForwardBox: gk, ForwardPath: "3e325e6ab86420d1ae1f36242db87f0e"})
b.SetResolver("test/1_data.sql", packr.Pointer{ForwardBox: gk, ForwardPath: "a8de4218a101c7dbc4005b492e2f7fa1"})
b.SetResolver("test/application.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "c6edd0d1e59c8ee63811b57d99aa4f20"})
b.SetResolver("test/db.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "0bf2c3c279f0863ca37680167a1668e2"})
b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "225361cfe91f8a3ee02db98f64637aa4"}) b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "225361cfe91f8a3ee02db98f64637aa4"})
b.SetResolver("test/grpc.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "5d9b1138f620733adbad0acfb294d661"})
b.SetResolver("test/memcache.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "191590fe9aea37da87e1139609a72c5b"})
b.SetResolver("test/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "29d20d6ca71bd38c525aa7a6728b3c5d"})
}() }()
@ -159,15 +206,24 @@ var _ = func() error {
b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "40aa45750f8397d706e3d8fdd82fa11f"}) b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "40aa45750f8397d706e3d8fdd82fa11f"})
b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "f6e84ad3fd70355fca59f33e23639704"}) b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "f6e84ad3fd70355fca59f33e23639704"})
b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d1ce3e717c8a1e9830e9e1626ff88fa8"}) b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d1ce3e717c8a1e9830e9e1626ff88fa8"})
b.SetResolver("internal/dao/dao_test.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "4ad10871b856157d685556dee22622df"})
b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "676482aadd24e9539226c67ebd8b5d04"}) b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "676482aadd24e9539226c67ebd8b5d04"})
b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "cdc9702cf3b30ddc315510a28df1ff83"}) b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "cdc9702cf3b30ddc315510a28df1ff83"})
b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "aa6f74a5b61f4cf11f0d49914680fd21"}) b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "aa6f74a5b61f4cf11f0d49914680fd21"})
b.SetResolver("internal/dao/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "b548f55cb04df40183977ace8191f981"})
b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "56d831af18f731847e4733aa321128cb"}) b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "56d831af18f731847e4733aa321128cb"})
b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "8f2519501a642ae50acf464ad3acb9f9"}) b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "8f2519501a642ae50acf464ad3acb9f9"})
b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "fe2a9fe5f84f01e208243862890c2182"}) b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "fe2a9fe5f84f01e208243862890c2182"})
b.SetResolver("internal/server/http/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "46713bf4406bd2896c32e5778efb1eb5"}) b.SetResolver("internal/server/http/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "46713bf4406bd2896c32e5778efb1eb5"})
b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d5f9b4870ad447f7ef808033db2803ad"}) b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d5f9b4870ad447f7ef808033db2803ad"})
b.SetResolver("test/0_db.sql", packr.Pointer{ForwardBox: gk, ForwardPath: "08a57ee8c539d8871f262cf7a361df41"})
b.SetResolver("test/1_data.sql", packr.Pointer{ForwardBox: gk, ForwardPath: "9b304970a0564dd9317fcd5d626e58a4"})
b.SetResolver("test/application.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "e3f75655d10714df86daec6cb01335fb"})
b.SetResolver("test/db.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "d3c2a7dd82dae9f20e2fc67b98fb3a9e"})
b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "14b27f88168b4f08f9d703f2a9b5027c"}) b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "14b27f88168b4f08f9d703f2a9b5027c"})
b.SetResolver("test/http.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "9633293b1618913c69833784cc3e25d2"})
b.SetResolver("test/memcache.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "fc66ed973976512794d4a2930aa4060d"})
b.SetResolver("test/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "b0d155056e1d877b853104fa73d7dc20"})
}() }()
return nil return nil

@ -58,14 +58,17 @@ func create() (err error) {
} }
} }
if err = generate(); err != nil { if err = generate("./..."); err != nil {
return
}
if err = generate("./internal/dao/wire.go"); err != nil {
return return
} }
return return
} }
func generate() error { func generate(path string) error {
cmd := exec.Command("go", "generate", "./...") cmd := exec.Command("go", "generate", "-x", path)
cmd.Dir = p.path cmd.Dir = p.path
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr

@ -10,25 +10,25 @@ import "google/api/annotations.proto";
// package 使 {appid}.{version} , version v1, v2 .. // package 使 {appid}.{version} , version v1, v2 ..
package demo.service.v1; package demo.service.v1;
// NOTE: (-) // NOTE: (-)
option go_package = "api"; option go_package = "api";
option (gogoproto.goproto_getters_all) = false; option (gogoproto.goproto_getters_all) = false;
service Demo { service Demo {
rpc Ping (.google.protobuf.Empty) returns (.google.protobuf.Empty); rpc Ping(.google.protobuf.Empty) returns (.google.protobuf.Empty);
rpc SayHello (HelloReq) returns (.google.protobuf.Empty); rpc SayHello(HelloReq) returns (.google.protobuf.Empty);
rpc SayHelloURL(HelloReq) returns (HelloResp) { rpc SayHelloURL(HelloReq) returns (HelloResp) {
option (google.api.http) = { option (google.api.http) = {
get:"/kratos-demo/say_hello" get: "/kratos-demo/say_hello"
};
}; };
};
} }
message HelloReq { message HelloReq {
string name = 1 [(gogoproto.moretags)='form:"name" validate:"required"']; string name = 1 [(gogoproto.moretags) = 'form:"name" validate:"required"'];
} }
message HelloResp { message HelloResp {
string Content = 1 [(gogoproto.jsontag) = 'content']; string Content = 1 [(gogoproto.jsontag) = 'content'];
} }

@ -1,11 +1,12 @@
module {{.Name}} module {{.Name}}
go 1.12 go 1.13
require ( require (
github.com/bilibili/kratos master github.com/bilibili/kratos master
github.com/gogo/protobuf v1.2.1 github.com/gogo/protobuf v1.2.1
github.com/golang/protobuf v1.3.2 github.com/golang/protobuf v1.3.2
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 golang.org/x/net v0.0.0-20190628185345-da137c7871d7
google.golang.org/grpc v1.22.0 google.golang.org/grpc v1.22.0
) )

@ -11,8 +11,12 @@ import (
"github.com/bilibili/kratos/pkg/database/sql" "github.com/bilibili/kratos/pkg/database/sql"
"github.com/bilibili/kratos/pkg/sync/pipeline/fanout" "github.com/bilibili/kratos/pkg/sync/pipeline/fanout"
xtime "github.com/bilibili/kratos/pkg/time" xtime "github.com/bilibili/kratos/pkg/time"
"github.com/google/wire"
) )
var Provider = wire.NewSet(New, NewDB, NewRedis, NewMC)
//go:generate kratos tool genbts //go:generate kratos tool genbts
// Dao dao interface // Dao dao interface
type Dao interface { type Dao interface {
@ -32,7 +36,11 @@ type dao struct {
} }
// New new a dao and return. // New new a dao and return.
func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) { func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, cf func(), err error) {
return newDao(r, mc, db)
}
func newDao(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d *dao, cf func(), err error) {
var cfg struct{ var cfg struct{
DemoExpire xtime.Duration DemoExpire xtime.Duration
} }
@ -46,14 +54,12 @@ func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) {
cache: fanout.New("cache"), cache: fanout.New("cache"),
demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second), demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second),
} }
cf = d.Close
return return
} }
// Close close the resource. // Close close the resource.
func (d *dao) Close() { func (d *dao) Close() {
d.mc.Close()
d.redis.Close()
d.db.Close()
d.cache.Close() d.cache.Close()
} }

@ -0,0 +1,40 @@
package dao
import (
"context"
"flag"
"os"
"testing"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/testing/lich"
)
var d *dao
var ctx = context.Background()
func TestMain(m *testing.M) {
flag.Set("conf", "../../test")
flag.Set("f", "../../test/docker-compose.yaml")
flag.Parse()
disableLich := os.Getenv("DISABLE_LICH") != ""
if !disableLich {
if err := lich.Setup(); err != nil {
panic(err)
}
}
var err error
if err = paladin.Init(); err != nil {
panic(err)
}
var cf func()
if d, cf, err = newTestDao();err != nil {
panic(err)
}
ret := m.Run()
cf()
if !disableLich {
_ = lich.Teardown()
}
os.Exit(ret)
}

@ -8,14 +8,19 @@ import (
"github.com/bilibili/kratos/pkg/database/sql" "github.com/bilibili/kratos/pkg/database/sql"
) )
func NewDB() (db *sql.DB, err error) { func NewDB() (db *sql.DB, cf func(), err error) {
var cfg struct { var (
Client *sql.Config cfg sql.Config
ct paladin.TOML
)
if err = paladin.Get("db.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("db.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
db = sql.NewMySQL(cfg.Client) db = sql.NewMySQL(&cfg)
cf = func() {db.Close()}
return return
} }

@ -20,14 +20,19 @@ type _mc interface {
DeleteArticleCache(c context.Context, id int64) (err error) DeleteArticleCache(c context.Context, id int64) (err error)
} }
func NewMC() (mc *memcache.Memcache, err error) { func NewMC() (mc *memcache.Memcache, cf func(), err error) {
var cfg struct { var (
Client *memcache.Config cfg memcache.Config
ct paladin.TOML
)
if err = paladin.Get("memcache.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("memcache.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
mc = memcache.New(cfg.Client) mc = memcache.New(&cfg)
cf = func() {mc.Close()}
return return
} }

@ -8,14 +8,19 @@ import (
"github.com/bilibili/kratos/pkg/log" "github.com/bilibili/kratos/pkg/log"
) )
func NewRedis() (r *redis.Redis, err error) { func NewRedis() (r *redis.Redis, cf func(), err error) {
var cfg struct { var (
Client *redis.Config cfg redis.Config
ct paladin.Map
)
if err = paladin.Get("redis.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("redis.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
r = redis.NewRedis(cfg.Client) r = redis.NewRedis(&cfg)
cf = func(){r.Close()}
return return
} }

@ -0,0 +1,13 @@
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package dao
import (
"github.com/google/wire"
)
//go:generate kratos tool wire
func newTestDao() (*dao, func(), error) {
panic(wire.Build(newDao, NewDB, NewRedis, NewMC))
}

@ -32,7 +32,6 @@ func NewApp(svc *service.Service, h *bm.Engine, g *warden.Server) (app *App, clo
if err := h.Shutdown(ctx); err != nil { if err := h.Shutdown(ctx); err != nil {
log.Error("httpSrv.Shutdown error(%v)", err) log.Error("httpSrv.Shutdown error(%v)", err)
} }
svc.Close()
cancel() cancel()
} }
return return

@ -4,18 +4,15 @@
package di package di
import ( import (
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao" "{{.ModPrefix}}{{.Name}}/internal/dao"
"{{.ModPrefix}}{{.Name}}/internal/service"
"{{.ModPrefix}}{{.Name}}/internal/server/grpc" "{{.ModPrefix}}{{.Name}}/internal/server/grpc"
"{{.ModPrefix}}{{.Name}}/internal/server/http" "{{.ModPrefix}}{{.Name}}/internal/server/http"
"{{.ModPrefix}}{{.Name}}/internal/service"
"github.com/google/wire" "github.com/google/wire"
) )
var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC) //go:generate kratos t wire
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))
func InitApp() (*App, func(), error) { func InitApp() (*App, func(), error) {
panic(wire.Build(daoProvider, serviceProvider, http.New, grpc.New, NewApp)) panic(wire.Build(dao.Provider, service.Provider, http.New, grpc.New, NewApp))
} }

@ -9,14 +9,17 @@ import (
// New new a grpc server. // New new a grpc server.
func New(svc pb.DemoServer) (ws *warden.Server, err error) { func New(svc pb.DemoServer) (ws *warden.Server, err error) {
var rc struct { var (
Server *warden.ServerConfig cfg warden.ServerConfig
ct paladin.TOML
)
if err = paladin.Get("grpc.toml").Unmarshal(&ct); err != nil {
return
} }
err = paladin.Get("grpc.toml").UnmarshalTOML(&rc) if err = ct.Get("Server").UnmarshalTOML(&cfg); err != nil {
if err == paladin.ErrNotExist { return
err = nil
} }
ws = warden.NewServer(rc.Server) ws = warden.NewServer(&cfg)
pb.RegisterDemoServer(ws.Server(), svc) pb.RegisterDemoServer(ws.Server(), svc)
ws, err = ws.Start() ws, err = ws.Start()
return return

@ -15,18 +15,17 @@ var svc pb.DemoServer
// New new a bm server. // New new a bm server.
func New(s pb.DemoServer) (engine *bm.Engine, err error) { func New(s pb.DemoServer) (engine *bm.Engine, err error) {
var ( var (
hc struct { cfg bm.ServerConfig
Server *bm.ServerConfig ct paladin.TOML
}
) )
if err = paladin.Get("http.toml").UnmarshalTOML(&hc); err != nil { if err = paladin.Get("http.toml").Unmarshal(&ct); err != nil {
if err != paladin.ErrNotExist { return
return }
} if err = ct.Get("Server").UnmarshalTOML(&cfg); err != nil {
err = nil return
} }
svc = s svc = s
engine = bm.DefaultServer(hc.Server) engine = bm.DefaultServer(&cfg)
pb.RegisterDemoBMServer(engine, s) pb.RegisterDemoBMServer(engine, s)
initRouter(engine) initRouter(engine)
err = engine.Start() err = engine.Start()

@ -9,8 +9,11 @@ import (
"github.com/bilibili/kratos/pkg/conf/paladin" "github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/empty"
"github.com/google/wire"
) )
var Provider = wire.NewSet(New, wire.Bind(new(pb.DemoServer), new(*Service)))
// Service service. // Service service.
type Service struct { type Service struct {
ac *paladin.Map ac *paladin.Map
@ -18,11 +21,12 @@ type Service struct {
} }
// New new a service and return. // New new a service and return.
func New(d dao.Dao) (s *Service, err error) { func New(d dao.Dao) (s *Service, cf func(), err error) {
s = &Service{ s = &Service{
ac: &paladin.TOML{}, ac: &paladin.TOML{},
dao: d, dao: d,
} }
cf = s.Close
err = paladin.Watch("application.toml", s.ac) err = paladin.Watch("application.toml", s.ac)
return return
} }
@ -50,5 +54,4 @@ func (s *Service) Ping(ctx context.Context, e *empty.Empty) (*empty.Empty, error
// Close close the resource. // Close close the resource.
func (s *Service) Close() { func (s *Service) Close() {
s.dao.Close()
} }

@ -0,0 +1,11 @@
create database kratos_demo;
use kratos_demo;
CREATE TABLE `articles` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`title` varchar(64) NOT NULL COMMENT '名称',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `ix_mtime` (`mtime`)
) COMMENT='文章表';

@ -0,0 +1,3 @@
use kratos_demo;
INSERT INTO articles(`id`, `title`) VALUES (1, 'title');

@ -0,0 +1,3 @@
# This is a TOML document. Boom~
demoExpire = "24h"

@ -0,0 +1,8 @@
[Client]
dsn = "root:root@tcp(127.0.0.1:13306)/kratos_demo?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "300ms"
tranTimeout = "400ms"

@ -3,7 +3,7 @@
db: db:
image: mysql:5.6 image: mysql:5.6
ports: ports:
- 3306:3306 - 13306:3306
environment: environment:
- MYSQL_ROOT_PASSWORD=root - MYSQL_ROOT_PASSWORD=root
- TZ=Asia/Shanghai - TZ=Asia/Shanghai
@ -22,7 +22,7 @@
redis: redis:
image: redis image: redis
ports: ports:
- 6379:6379 - 16379:6379
healthcheck: healthcheck:
test: ["CMD", "redis-cli","ping"] test: ["CMD", "redis-cli","ping"]
interval: 20s interval: 20s
@ -32,7 +32,7 @@
memcached: memcached:
image: memcached image: memcached
ports: ports:
- 11211:11211 - 21211:11211
healthcheck: healthcheck:
test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"] test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"]
interval: 20s interval: 20s

@ -0,0 +1,3 @@
[Server]
addr = "0.0.0.0:9000"
timeout = "1s"

@ -0,0 +1,3 @@
[Server]
addr = "0.0.0.0:8000"
timeout = "1s"

@ -0,0 +1,10 @@
[Client]
name = "demo"
proto = "tcp"
addr = "127.0.0.1:21211"
active = 50
idle = 10
dialTimeout = "100ms"
readTimeout = "200ms"
writeTimeout = "300ms"
idleTimeout = "80s"

@ -0,0 +1,10 @@
[Client]
name = "demo"
proto = "tcp"
addr = "127.0.0.1:16379"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"

@ -1,2 +1,2 @@
# Author # Author
# Reviewer # Reviewer

@ -10,25 +10,25 @@ import "google/api/annotations.proto";
// package 使 {appid}.{version} , version v1, v2 .. // package 使 {appid}.{version} , version v1, v2 ..
package demo.service.v1; package demo.service.v1;
// NOTE: (-) // NOTE: (-)
option go_package = "api"; option go_package = "api";
option (gogoproto.goproto_getters_all) = false; option (gogoproto.goproto_getters_all) = false;
service Demo { service Demo {
rpc Ping (.google.protobuf.Empty) returns (.google.protobuf.Empty); rpc Ping(.google.protobuf.Empty) returns (.google.protobuf.Empty);
rpc SayHello (HelloReq) returns (.google.protobuf.Empty); rpc SayHello(HelloReq) returns (.google.protobuf.Empty);
rpc SayHelloURL(HelloReq) returns (HelloResp) { rpc SayHelloURL(HelloReq) returns (HelloResp) {
option (google.api.http) = { option (google.api.http) = {
get:"/kratos-demo/say_hello" get: "/kratos-demo/say_hello"
};
}; };
};
} }
message HelloReq { message HelloReq {
string name = 1 [(gogoproto.moretags)='form:"name" validate:"required"']; string name = 1 [(gogoproto.moretags) = 'form:"name" validate:"required"'];
} }
message HelloResp { message HelloResp {
string Content = 1 [(gogoproto.jsontag) = 'content']; string Content = 1 [(gogoproto.jsontag) = 'content'];
} }

@ -1,11 +1,12 @@
module {{.Name}} module {{.Name}}
go 1.12 go 1.13
require ( require (
github.com/bilibili/kratos master github.com/bilibili/kratos master
github.com/gogo/protobuf v1.2.1 github.com/gogo/protobuf v1.2.1
github.com/golang/protobuf v1.3.2 github.com/golang/protobuf v1.3.2
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 golang.org/x/net v0.0.0-20190628185345-da137c7871d7
google.golang.org/grpc v1.22.0 google.golang.org/grpc v1.22.0
) )

@ -11,8 +11,12 @@ import (
"github.com/bilibili/kratos/pkg/database/sql" "github.com/bilibili/kratos/pkg/database/sql"
"github.com/bilibili/kratos/pkg/sync/pipeline/fanout" "github.com/bilibili/kratos/pkg/sync/pipeline/fanout"
xtime "github.com/bilibili/kratos/pkg/time" xtime "github.com/bilibili/kratos/pkg/time"
"github.com/google/wire"
) )
var Provider = wire.NewSet(New, NewDB, NewRedis, NewMC)
//go:generate kratos tool genbts //go:generate kratos tool genbts
// Dao dao interface // Dao dao interface
type Dao interface { type Dao interface {
@ -32,7 +36,11 @@ type dao struct {
} }
// New new a dao and return. // New new a dao and return.
func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) { func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, cf func(), err error) {
return newDao(r, mc, db)
}
func newDao(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d *dao, cf func(), err error) {
var cfg struct{ var cfg struct{
DemoExpire xtime.Duration DemoExpire xtime.Duration
} }
@ -46,14 +54,12 @@ func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) {
cache: fanout.New("cache"), cache: fanout.New("cache"),
demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second), demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second),
} }
cf = d.Close
return return
} }
// Close close the resource. // Close close the resource.
func (d *dao) Close() { func (d *dao) Close() {
d.mc.Close()
d.redis.Close()
d.db.Close()
d.cache.Close() d.cache.Close()
} }

@ -0,0 +1,40 @@
package dao
import (
"context"
"flag"
"os"
"testing"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/testing/lich"
)
var d *dao
var ctx = context.Background()
func TestMain(m *testing.M) {
flag.Set("conf", "../../test")
flag.Set("f", "../../test/docker-compose.yaml")
flag.Parse()
disableLich := os.Getenv("DISABLE_LICH") != ""
if !disableLich {
if err := lich.Setup(); err != nil {
panic(err)
}
}
var err error
if err = paladin.Init(); err != nil {
panic(err)
}
var cf func()
if d, cf, err = newTestDao();err != nil {
panic(err)
}
ret := m.Run()
cf()
if !disableLich {
_ = lich.Teardown()
}
os.Exit(ret)
}

@ -8,14 +8,19 @@ import (
"github.com/bilibili/kratos/pkg/database/sql" "github.com/bilibili/kratos/pkg/database/sql"
) )
func NewDB() (db *sql.DB, err error) { func NewDB() (db *sql.DB, cf func(), err error) {
var cfg struct { var (
Client *sql.Config cfg sql.Config
ct paladin.TOML
)
if err = paladin.Get("db.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("db.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
db = sql.NewMySQL(cfg.Client) db = sql.NewMySQL(&cfg)
cf = func() {db.Close()}
return return
} }

@ -20,14 +20,19 @@ type _mc interface {
DeleteArticleCache(c context.Context, id int64) (err error) DeleteArticleCache(c context.Context, id int64) (err error)
} }
func NewMC() (mc *memcache.Memcache, err error) { func NewMC() (mc *memcache.Memcache, cf func(), err error) {
var cfg struct { var (
Client *memcache.Config cfg memcache.Config
ct paladin.TOML
)
if err = paladin.Get("memcache.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("memcache.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
mc = memcache.New(cfg.Client) mc = memcache.New(&cfg)
cf = func() {mc.Close()}
return return
} }

@ -8,14 +8,19 @@ import (
"github.com/bilibili/kratos/pkg/log" "github.com/bilibili/kratos/pkg/log"
) )
func NewRedis() (r *redis.Redis, err error) { func NewRedis() (r *redis.Redis, cf func(), err error) {
var cfg struct { var (
Client *redis.Config cfg redis.Config
ct paladin.Map
)
if err = paladin.Get("redis.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("redis.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
r = redis.NewRedis(cfg.Client) r = redis.NewRedis(&cfg)
cf = func(){r.Close()}
return return
} }

@ -0,0 +1,13 @@
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package dao
import (
"github.com/google/wire"
)
//go:generate kratos tool wire
func newTestDao() (*dao, func(), error) {
panic(wire.Build(newDao, NewDB, NewRedis, NewMC))
}

@ -26,7 +26,6 @@ func NewApp(svc *service.Service, g *warden.Server) (app *App, closeFunc func(),
if err := g.Shutdown(ctx); err != nil { if err := g.Shutdown(ctx); err != nil {
log.Error("grpcSrv.Shutdown error(%v)", err) log.Error("grpcSrv.Shutdown error(%v)", err)
} }
svc.Close()
cancel() cancel()
} }
return return

@ -4,17 +4,14 @@
package di package di
import ( import (
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao" "{{.ModPrefix}}{{.Name}}/internal/dao"
"{{.ModPrefix}}{{.Name}}/internal/server/grpc"
"{{.ModPrefix}}{{.Name}}/internal/service" "{{.ModPrefix}}{{.Name}}/internal/service"
"{{.ModPrefix}}{{.Name}}/internal/server/grpc"
"github.com/google/wire" "github.com/google/wire"
) )
var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC) //go:generate kratos t wire
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))
func InitApp() (*App, func(), error) { func InitApp() (*App, func(), error) {
panic(wire.Build(daoProvider, serviceProvider, grpc.New, NewApp)) panic(wire.Build(dao.Provider, service.Provider, grpc.New, NewApp))
} }

@ -9,14 +9,17 @@ import (
// New new a grpc server. // New new a grpc server.
func New(svc pb.DemoServer) (ws *warden.Server, err error) { func New(svc pb.DemoServer) (ws *warden.Server, err error) {
var rc struct { var (
Server *warden.ServerConfig cfg warden.ServerConfig
ct paladin.TOML
)
if err = paladin.Get("grpc.toml").Unmarshal(&ct); err != nil {
return
} }
err = paladin.Get("grpc.toml").UnmarshalTOML(&rc) if err = ct.Get("Server").UnmarshalTOML(&cfg); err != nil {
if err == paladin.ErrNotExist { return
err = nil
} }
ws = warden.NewServer(rc.Server) ws = warden.NewServer(&cfg)
pb.RegisterDemoServer(ws.Server(), svc) pb.RegisterDemoServer(ws.Server(), svc)
ws, err = ws.Start() ws, err = ws.Start()
return return

@ -9,8 +9,11 @@ import (
"github.com/bilibili/kratos/pkg/conf/paladin" "github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/empty"
"github.com/google/wire"
) )
var Provider = wire.NewSet(New, wire.Bind(new(pb.DemoServer), new(*Service)))
// Service service. // Service service.
type Service struct { type Service struct {
ac *paladin.Map ac *paladin.Map
@ -18,11 +21,12 @@ type Service struct {
} }
// New new a service and return. // New new a service and return.
func New(d dao.Dao) (s *Service, err error) { func New(d dao.Dao) (s *Service, cf func(), err error) {
s = &Service{ s = &Service{
ac: &paladin.TOML{}, ac: &paladin.TOML{},
dao: d, dao: d,
} }
cf = s.Close
err = paladin.Watch("application.toml", s.ac) err = paladin.Watch("application.toml", s.ac)
return return
} }
@ -50,5 +54,4 @@ func (s *Service) Ping(ctx context.Context, e *empty.Empty) (*empty.Empty, error
// Close close the resource. // Close close the resource.
func (s *Service) Close() { func (s *Service) Close() {
s.dao.Close()
} }

@ -0,0 +1,11 @@
create database kratos_demo;
use kratos_demo;
CREATE TABLE `articles` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`title` varchar(64) NOT NULL COMMENT '名称',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `ix_mtime` (`mtime`)
) COMMENT='文章表';

@ -0,0 +1,3 @@
use kratos_demo;
INSERT INTO articles(`id`, `title`) VALUES (1, 'title');

@ -0,0 +1,3 @@
# This is a TOML document. Boom~
demoExpire = "24h"

@ -0,0 +1,8 @@
[Client]
dsn = "root:root@tcp(127.0.0.1:13306)/kratos_demo?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "300ms"
tranTimeout = "400ms"

@ -3,7 +3,7 @@
db: db:
image: mysql:5.6 image: mysql:5.6
ports: ports:
- 3306:3306 - 13306:3306
environment: environment:
- MYSQL_ROOT_PASSWORD=root - MYSQL_ROOT_PASSWORD=root
- TZ=Asia/Shanghai - TZ=Asia/Shanghai
@ -22,7 +22,7 @@
redis: redis:
image: redis image: redis
ports: ports:
- 6379:6379 - 16379:6379
healthcheck: healthcheck:
test: ["CMD", "redis-cli","ping"] test: ["CMD", "redis-cli","ping"]
interval: 20s interval: 20s
@ -32,7 +32,7 @@
memcached: memcached:
image: memcached image: memcached
ports: ports:
- 11211:11211 - 21211:11211
healthcheck: healthcheck:
test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"] test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"]
interval: 20s interval: 20s

@ -0,0 +1,3 @@
[Server]
addr = "0.0.0.0:9000"
timeout = "1s"

@ -0,0 +1,10 @@
[Client]
name = "demo"
proto = "tcp"
addr = "127.0.0.1:21211"
active = 50
idle = 10
dialTimeout = "100ms"
readTimeout = "200ms"
writeTimeout = "300ms"
idleTimeout = "80s"

@ -0,0 +1,10 @@
[Client]
name = "demo"
proto = "tcp"
addr = "127.0.0.1:16379"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"

@ -10,25 +10,25 @@ import "google/api/annotations.proto";
// package 使 {appid}.{version} , version v1, v2 .. // package 使 {appid}.{version} , version v1, v2 ..
package demo.service.v1; package demo.service.v1;
// NOTE: (-) // NOTE: (-)
option go_package = "api"; option go_package = "api";
option (gogoproto.goproto_getters_all) = false; option (gogoproto.goproto_getters_all) = false;
service Demo { service Demo {
rpc Ping (.google.protobuf.Empty) returns (.google.protobuf.Empty); rpc Ping(.google.protobuf.Empty) returns (.google.protobuf.Empty);
rpc SayHello (HelloReq) returns (.google.protobuf.Empty); rpc SayHello(HelloReq) returns (.google.protobuf.Empty);
rpc SayHelloURL(HelloReq) returns (HelloResp) { rpc SayHelloURL(HelloReq) returns (HelloResp) {
option (google.api.http) = { option (google.api.http) = {
get:"/kratos-demo/say_hello" get: "/demo/say_hello"
};
}; };
};
} }
message HelloReq { message HelloReq {
string name = 1 [(gogoproto.moretags)='form:"name" validate:"required"']; string name = 1 [(gogoproto.moretags) = 'form:"name" validate:"required"'];
} }
message HelloResp { message HelloResp {
string Content = 1 [(gogoproto.jsontag) = 'content']; string Content = 1 [(gogoproto.jsontag) = 'content'];
} }

@ -1,11 +1,12 @@
module {{.Name}} module {{.Name}}
go 1.12 go 1.13
require ( require (
github.com/bilibili/kratos master github.com/bilibili/kratos master
github.com/gogo/protobuf v1.2.1 github.com/gogo/protobuf v1.2.1
github.com/golang/protobuf v1.3.2 github.com/golang/protobuf v1.3.2
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 golang.org/x/net v0.0.0-20190628185345-da137c7871d7
google.golang.org/grpc v1.22.0 google.golang.org/grpc v1.22.0
) )

@ -11,8 +11,12 @@ import (
"github.com/bilibili/kratos/pkg/database/sql" "github.com/bilibili/kratos/pkg/database/sql"
"github.com/bilibili/kratos/pkg/sync/pipeline/fanout" "github.com/bilibili/kratos/pkg/sync/pipeline/fanout"
xtime "github.com/bilibili/kratos/pkg/time" xtime "github.com/bilibili/kratos/pkg/time"
"github.com/google/wire"
) )
var Provider = wire.NewSet(New, NewDB, NewRedis, NewMC)
//go:generate kratos tool genbts //go:generate kratos tool genbts
// Dao dao interface // Dao dao interface
type Dao interface { type Dao interface {
@ -32,7 +36,11 @@ type dao struct {
} }
// New new a dao and return. // New new a dao and return.
func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) { func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, cf func(), err error) {
return newDao(r, mc, db)
}
func newDao(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d *dao, cf func(), err error) {
var cfg struct{ var cfg struct{
DemoExpire xtime.Duration DemoExpire xtime.Duration
} }
@ -46,14 +54,12 @@ func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) {
cache: fanout.New("cache"), cache: fanout.New("cache"),
demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second), demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second),
} }
cf = d.Close
return return
} }
// Close close the resource. // Close close the resource.
func (d *dao) Close() { func (d *dao) Close() {
d.mc.Close()
d.redis.Close()
d.db.Close()
d.cache.Close() d.cache.Close()
} }

@ -0,0 +1,40 @@
package dao
import (
"context"
"flag"
"os"
"testing"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/testing/lich"
)
var d *dao
var ctx = context.Background()
func TestMain(m *testing.M) {
flag.Set("conf", "../../test")
flag.Set("f", "../../test/docker-compose.yaml")
flag.Parse()
disableLich := os.Getenv("DISABLE_LICH") != ""
if !disableLich {
if err := lich.Setup(); err != nil {
panic(err)
}
}
var err error
if err = paladin.Init(); err != nil {
panic(err)
}
var cf func()
if d, cf, err = newTestDao();err != nil {
panic(err)
}
ret := m.Run()
cf()
if !disableLich {
_ = lich.Teardown()
}
os.Exit(ret)
}

@ -8,14 +8,19 @@ import (
"github.com/bilibili/kratos/pkg/database/sql" "github.com/bilibili/kratos/pkg/database/sql"
) )
func NewDB() (db *sql.DB, err error) { func NewDB() (db *sql.DB, cf func(), err error) {
var cfg struct { var (
Client *sql.Config cfg sql.Config
ct paladin.TOML
)
if err = paladin.Get("db.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("db.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
db = sql.NewMySQL(cfg.Client) db = sql.NewMySQL(&cfg)
cf = func() {db.Close()}
return return
} }

@ -20,14 +20,19 @@ type _mc interface {
DeleteArticleCache(c context.Context, id int64) (err error) DeleteArticleCache(c context.Context, id int64) (err error)
} }
func NewMC() (mc *memcache.Memcache, err error) { func NewMC() (mc *memcache.Memcache, cf func(), err error) {
var cfg struct { var (
Client *memcache.Config cfg memcache.Config
ct paladin.TOML
)
if err = paladin.Get("memcache.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("memcache.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
mc = memcache.New(cfg.Client) mc = memcache.New(&cfg)
cf = func() {mc.Close()}
return return
} }

@ -8,14 +8,19 @@ import (
"github.com/bilibili/kratos/pkg/log" "github.com/bilibili/kratos/pkg/log"
) )
func NewRedis() (r *redis.Redis, err error) { func NewRedis() (r *redis.Redis, cf func(), err error) {
var cfg struct { var (
Client *redis.Config cfg redis.Config
ct paladin.Map
)
if err = paladin.Get("redis.toml").Unmarshal(&ct); err != nil {
return
} }
if err = paladin.Get("redis.toml").UnmarshalTOML(&cfg); err != nil { if err = ct.Get("Client").UnmarshalTOML(&cfg); err != nil {
return return
} }
r = redis.NewRedis(cfg.Client) r = redis.NewRedis(&cfg)
cf = func(){r.Close()}
return return
} }

@ -0,0 +1,13 @@
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package dao
import (
"github.com/google/wire"
)
//go:generate kratos tool wire
func newTestDao() (*dao, func(), error) {
panic(wire.Build(newDao, NewDB, NewRedis, NewMC))
}

@ -26,7 +26,6 @@ func NewApp(svc *service.Service, h *bm.Engine) (app *App, closeFunc func(), err
if err := h.Shutdown(ctx); err != nil { if err := h.Shutdown(ctx); err != nil {
log.Error("httpSrv.Shutdown error(%v)", err) log.Error("httpSrv.Shutdown error(%v)", err)
} }
svc.Close()
cancel() cancel()
} }
return return

@ -4,17 +4,14 @@
package di package di
import ( import (
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao" "{{.ModPrefix}}{{.Name}}/internal/dao"
"{{.ModPrefix}}{{.Name}}/internal/server/http"
"{{.ModPrefix}}{{.Name}}/internal/service" "{{.ModPrefix}}{{.Name}}/internal/service"
"{{.ModPrefix}}{{.Name}}/internal/server/http"
"github.com/google/wire" "github.com/google/wire"
) )
var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC) //go:generate kratos t wire
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))
func InitApp() (*App, func(), error) { func InitApp() (*App, func(), error) {
panic(wire.Build(daoProvider, serviceProvider, http.New, NewApp)) panic(wire.Build(dao.Provider, service.Provider, http.New, NewApp))
} }

@ -15,18 +15,17 @@ var svc pb.DemoServer
// New new a bm server. // New new a bm server.
func New(s pb.DemoServer) (engine *bm.Engine, err error) { func New(s pb.DemoServer) (engine *bm.Engine, err error) {
var ( var (
hc struct { cfg bm.ServerConfig
Server *bm.ServerConfig ct paladin.TOML
}
) )
if err = paladin.Get("http.toml").UnmarshalTOML(&hc); err != nil { if err = paladin.Get("http.toml").Unmarshal(&ct); err != nil {
if err != paladin.ErrNotExist { return
return }
} if err = ct.Get("Server").UnmarshalTOML(&cfg); err != nil {
err = nil return
} }
svc = s svc = s
engine = bm.DefaultServer(hc.Server) engine = bm.DefaultServer(&cfg)
pb.RegisterDemoBMServer(engine, s) pb.RegisterDemoBMServer(engine, s)
initRouter(engine) initRouter(engine)
err = engine.Start() err = engine.Start()

@ -9,8 +9,11 @@ import (
"github.com/bilibili/kratos/pkg/conf/paladin" "github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/empty"
"github.com/google/wire"
) )
var Provider = wire.NewSet(New, wire.Bind(new(pb.DemoServer), new(*Service)))
// Service service. // Service service.
type Service struct { type Service struct {
ac *paladin.Map ac *paladin.Map
@ -18,11 +21,12 @@ type Service struct {
} }
// New new a service and return. // New new a service and return.
func New(d dao.Dao) (s *Service, err error) { func New(d dao.Dao) (s *Service, cf func(), err error) {
s = &Service{ s = &Service{
ac: &paladin.TOML{}, ac: &paladin.TOML{},
dao: d, dao: d,
} }
cf = s.Close
err = paladin.Watch("application.toml", s.ac) err = paladin.Watch("application.toml", s.ac)
return return
} }
@ -50,5 +54,4 @@ func (s *Service) Ping(ctx context.Context, e *empty.Empty) (*empty.Empty, error
// Close close the resource. // Close close the resource.
func (s *Service) Close() { func (s *Service) Close() {
s.dao.Close()
} }

@ -0,0 +1,11 @@
create database kratos_demo;
use kratos_demo;
CREATE TABLE `articles` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`title` varchar(64) NOT NULL COMMENT '名称',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `ix_mtime` (`mtime`)
) COMMENT='文章表';

@ -0,0 +1,3 @@
use kratos_demo;
INSERT INTO articles(`id`, `title`) VALUES (1, 'title');

@ -0,0 +1,3 @@
# This is a TOML document. Boom~
demoExpire = "24h"

@ -0,0 +1,8 @@
[Client]
dsn = "root:root@tcp(127.0.0.1:13306)/kratos_demo?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "300ms"
tranTimeout = "400ms"

@ -3,7 +3,7 @@
db: db:
image: mysql:5.6 image: mysql:5.6
ports: ports:
- 3306:3306 - 13306:3306
environment: environment:
- MYSQL_ROOT_PASSWORD=root - MYSQL_ROOT_PASSWORD=root
- TZ=Asia/Shanghai - TZ=Asia/Shanghai
@ -22,7 +22,7 @@
redis: redis:
image: redis image: redis
ports: ports:
- 6379:6379 - 16379:6379
healthcheck: healthcheck:
test: ["CMD", "redis-cli","ping"] test: ["CMD", "redis-cli","ping"]
interval: 20s interval: 20s
@ -32,7 +32,7 @@
memcached: memcached:
image: memcached image: memcached
ports: ports:
- 11211:11211 - 21211:11211
healthcheck: healthcheck:
test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"] test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"]
interval: 20s interval: 20s

@ -0,0 +1,3 @@
[Server]
addr = "0.0.0.0:8000"
timeout = "1s"

@ -0,0 +1,10 @@
[Client]
name = "demo"
proto = "tcp"
addr = "127.0.0.1:21211"
active = 50
idle = 10
dialTimeout = "100ms"
readTimeout = "200ms"
writeTimeout = "300ms"
idleTimeout = "80s"

@ -0,0 +1,10 @@
[Client]
name = "demo"
proto = "tcp"
addr = "127.0.0.1:16379"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"

@ -1,27 +1,37 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
dir=`pwd`
cd $dir
rm -rf ./a rm -rf ./a
kratos new a kratos new a
cd ./a/cmd && go build cd ./a/cmd && go build
if [ $? -ne 0 ] if [ $? -ne 0 ]; then
then
echo "Failed: all" echo "Failed: all"
exit 1 exit 1
else
rm -rf ../../a
fi fi
cd $dir
rm -rf ./b rm -rf ./b
kratos new b --grpc kratos new b --grpc
cd ./b/cmd && go build cd ./b/cmd && go build
if [ $? -ne 0 ] if [ $? -ne 0 ];then
then
echo "Failed: --grpc" echo "Failed: --grpc"
exit 1 exit 1
else
rm -rf ../../b
fi fi
cd $dir
rm -rf ./c rm -rf ./c
kratos new c --http kratos new c --http
cd ./c/cmd && go build cd ./c/cmd && go build
if [ $? -ne 0 ] if [ $? -ne 0 ]; then
then
echo "Failed: --http" echo "Failed: --http"
exit 1 exit 1
else
rm -rf ../../c
fi fi

@ -1,26 +1,41 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
rm -rf /tmp/test-kratos dir=/tmp/test-kratos
mkdir /tmp/test-kratos rm -rf $dir
kratos new a -d /tmp/test-kratos mkdir $dir
cd /tmp/test-kratos/a/cmd && go build
if [ $? -ne 0 ] cd $dir
then rm -rf ./a
kratos new a
cd ./a/cmd && go build
if [ $? -ne 0 ]; then
echo "Failed: all" echo "Failed: all"
exit 1 exit 1
else
rm -rf ../../a
fi fi
kratos new b -d /tmp/test-kratos --grpc
cd /tmp/test-kratos/b/cmd && go build cd $dir
if [ $? -ne 0 ] rm -rf ./b
then kratos new b --grpc
cd ./b/cmd && go build
if [ $? -ne 0 ];then
echo "Failed: --grpc" echo "Failed: --grpc"
exit 1 exit 1
else
rm -rf ../../b
fi fi
kratos new c -d /tmp/test-kratos --http
cd /tmp/test-kratos/c/cmd && go build cd $dir
if [ $? -ne 0 ] rm -rf ./c
then kratos new c --http
cd ./c/cmd && go build
if [ $? -ne 0 ]; then
echo "Failed: --http" echo "Failed: --http"
exit 1 exit 1
else
rm -rf ../../c
fi fi
rm -rf $dir

@ -61,7 +61,7 @@ var toolIndexs = []*Tool{
Name: "genproject", Name: "genproject",
Alias: "kratos-gen-project", Alias: "kratos-gen-project",
Install: "go get -u github.com/bilibili/kratos/tool/kratos-gen-project", Install: "go get -u github.com/bilibili/kratos/tool/kratos-gen-project",
BuildTime: time.Date(2019, 11, 6, 0, 0, 0, 0, time.Local), BuildTime: time.Date(2019, 12, 22, 0, 0, 0, 0, time.Local),
Platform: []string{"darwin", "linux", "windows"}, Platform: []string{"darwin", "linux", "windows"},
Hidden: true, Hidden: true,
Requirements: []string{"wire"}, Requirements: []string{"wire"},

@ -8,9 +8,9 @@ import (
var ( var (
// Version is version // Version is version
Version = "0.3.1" Version = "0.3.2"
// BuildTime is BuildTime // BuildTime is BuildTime
BuildTime = "2019/11/06" BuildTime = "2019/12/19"
) )
// VersionOptions include version // VersionOptions include version

Loading…
Cancel
Save