Commit 9554a130 authored by gejun's avatar gejun
parents 70d77b20 5eaf488d
......@@ -10,6 +10,7 @@
#include "json_to_pb.h"
#include "zero_copy_stream_reader.h" // ZeroCopyStreamReader
#include "encode_decode.h"
#include "base/base64.h"
#include "base/string_printf.h"
#include "protobuf_map.h"
#include "rapidjson.h"
......@@ -24,6 +25,14 @@
namespace json2pb {
Json2PbOptions::Json2PbOptions()
#ifdef BAIDU_INTERNAL
: base64_to_bytes(false) {
#else
: base64_to_bytes(true) {
#endif
}
enum MatchType {
TYPE_MATCH = 0x00,
REQUIRED_OR_REPEATED_TYPE_MISMATCH = 0x01,
......@@ -182,7 +191,9 @@ inline bool convert_enum_type(const rapidjson::Value&item, bool repeated,
}
bool JsonValueToProtoMessage(const rapidjson::Value& json_value,
google::protobuf::Message* message, std::string* err);
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* err);
//Json value to protobuf convert rules for type:
//Json value type Protobuf type convert rules
......@@ -208,7 +219,9 @@ bool JsonValueToProtoMessage(const rapidjson::Value& json_value,
static bool JsonValueToProtoField(const rapidjson::Value& value,
const google::protobuf::FieldDescriptor* field,
google::protobuf::Message* message, std::string* err) {
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* err) {
if (value.IsNull()) {
if (field->is_required()) {
J2PERROR(err, "Missing required field: %s", field->full_name().c_str());
......@@ -288,11 +301,29 @@ static bool JsonValueToProtoField(const rapidjson::Value& value,
const rapidjson::Value & item = value[index];
if (TYPE_MATCH == J2PCHECKTYPE(item, string, String)) {
std::string str(item.GetString(), item.GetStringLength());
if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES &&
options.base64_to_bytes) {
std::string str_decoded;
if (!base::Base64Decode(str, &str_decoded)) {
J2PERROR(err, "Fail to decode base64 string=%s", str.c_str());
return false;
}
str = str_decoded;
}
reflection->AddString(message, field, str);
}
}
} else if (TYPE_MATCH == J2PCHECKTYPE(value, string, String)) {
std::string str(value.GetString(), value.GetStringLength());
if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES &&
options.base64_to_bytes) {
std::string str_decoded;
if (!base::Base64Decode(str, &str_decoded)) {
J2PERROR(err, "Fail to decode base64 string=%s", str.c_str());
return false;
}
str = str_decoded;
}
reflection->SetString(message, field, str);
}
break;
......@@ -320,13 +351,13 @@ static bool JsonValueToProtoField(const rapidjson::Value& value,
const rapidjson::Value& item = value[index];
if (TYPE_MATCH == J2PCHECKTYPE(item, message, Object)) {
if (!JsonValueToProtoMessage(
item, reflection->AddMessage(message, field), err)) {
item, reflection->AddMessage(message, field), options, err)) {
return false;
}
}
}
} else if (!JsonValueToProtoMessage(
value, reflection->MutableMessage(message, field), err)) {
value, reflection->MutableMessage(message, field), options, err)) {
return false;
}
break;
......@@ -336,7 +367,9 @@ static bool JsonValueToProtoField(const rapidjson::Value& value,
bool JsonMapToProtoMap(const rapidjson::Value& value,
const google::protobuf::FieldDescriptor* map_desc,
google::protobuf::Message* message, std::string* err) {
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* err) {
if (!value.IsObject()) {
J2PERROR(err, "Non-object value for map field: %s",
map_desc->full_name().c_str());
......@@ -356,7 +389,7 @@ bool JsonMapToProtoMap(const rapidjson::Value& value,
entry_reflection->SetString(
entry, key_desc, std::string(it->name.GetString(),
it->name.GetStringLength()));
if (!JsonValueToProtoField(it->value, value_desc, entry, err)) {
if (!JsonValueToProtoField(it->value, value_desc, entry, options, err)) {
return false;
}
}
......@@ -364,7 +397,9 @@ bool JsonMapToProtoMap(const rapidjson::Value& value,
}
bool JsonValueToProtoMessage(const rapidjson::Value& json_value,
google::protobuf::Message* message, std::string* err) {
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* err) {
if (!json_value.IsObject()) {
J2PERROR(err, "`json_value' is not a json object");
return false;
......@@ -426,11 +461,11 @@ bool JsonValueToProtoMessage(const rapidjson::Value& json_value,
if (IsProtobufMap(field) && value_ptr->IsObject()) {
// Try to parse json like {"key":value, ...} into protobuf map
if (!JsonMapToProtoMap(*value_ptr, field, message, err)) {
if (!JsonMapToProtoMap(*value_ptr, field, message, options, err)) {
return false;
}
} else {
if (!JsonValueToProtoField(*value_ptr, field, message, err)) {
if (!JsonValueToProtoField(*value_ptr, field, message, options, err)) {
return false;
}
}
......@@ -447,19 +482,42 @@ bool ZeroCopyStreamToJson(rapidjson::Document *dest,
inline bool JsonToProtoMessageInline(const std::string& json_string,
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* error) {
if (error) {
error->clear();
}
rapidjson::Document d;
d.Parse<0>(json_string.c_str());
return json2pb::JsonValueToProtoMessage(d, message, error);
return json2pb::JsonValueToProtoMessage(d, message, options, error);
}
bool JsonToProtoMessage(const std::string& json_string,
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* error) {
return JsonToProtoMessageInline(json_string, message, options, error);
}
bool JsonToProtoMessage(google::protobuf::io::ZeroCopyInputStream* stream,
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* error) {
if (error) {
error->clear();
}
rapidjson::Document d;
if (!json2pb::ZeroCopyStreamToJson(&d, stream)) {
J2PERROR(error, "Invalid json format");
return false;
}
return json2pb::JsonValueToProtoMessage(d, message, options, error);
}
bool JsonToProtoMessage(const std::string& json_string,
google::protobuf::Message* message,
std::string* error) {
return JsonToProtoMessageInline(json_string, message, error);
return JsonToProtoMessageInline(json_string, message, Json2PbOptions(), error);
}
// For ABI compatibility with 1.0.0.0
......@@ -469,7 +527,7 @@ bool JsonToProtoMessage(const std::string& json_string,
bool JsonToProtoMessage(std::string json_string,
google::protobuf::Message* message,
std::string* error) {
return JsonToProtoMessageInline(json_string, message, error);
return JsonToProtoMessageInline(json_string, message, Json2PbOptions(), error);
}
bool JsonToProtoMessage(google::protobuf::io::ZeroCopyInputStream *stream,
......@@ -483,7 +541,7 @@ bool JsonToProtoMessage(google::protobuf::io::ZeroCopyInputStream *stream,
J2PERROR(error, "Invalid json format");
return false;
}
return json2pb::JsonValueToProtoMessage(d, message, error);
return json2pb::JsonValueToProtoMessage(d, message, Json2PbOptions(), error);
}
} //namespace json2pb
......
......@@ -11,6 +11,16 @@
#include <google/protobuf/io/zero_copy_stream.h> // ZeroCopyInputStream
namespace json2pb {
struct Json2PbOptions {
Json2PbOptions();
// Decode string in json using base64 decoding if the type of
// corresponding field is bytes when this option is turned on.
// Default: false for baidu-interal, true otherwise.
bool base64_to_bytes;
};
// Rules: http://wiki.baidu.com/display/RPC/Json+%3C%3D%3E+Protobuf
// Convert `json' to protobuf `message'.
......@@ -18,12 +28,23 @@ namespace json2pb {
// message on failure.
bool JsonToProtoMessage(const std::string& json,
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* error = NULL);
// send output to ZeroCopyOutputStream instead of std::string.
bool JsonToProtoMessage(google::protobuf::io::ZeroCopyInputStream *json,
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* error = NULL);
// Using default Json2PbOptions.
bool JsonToProtoMessage(const std::string& json,
google::protobuf::Message* message,
std::string* error = NULL);
bool JsonToProtoMessage(google::protobuf::io::ZeroCopyInputStream* stream,
google::protobuf::Message* message,
std::string* error = NULL);
}
} // namespace json2pb
#endif // BRPC_JSON2PB_JSON_TO_PB_H
......@@ -5,6 +5,7 @@
#include <sys/time.h>
#include <time.h>
#include <google/protobuf/descriptor.h>
#include "base/base64.h"
#include "zero_copy_stream_writer.h"
#include "encode_decode.h"
#include "protobuf_map.h"
......@@ -15,7 +16,12 @@ namespace json2pb {
Pb2JsonOptions::Pb2JsonOptions()
: enum_option(OUTPUT_ENUM_BY_NAME)
, pretty_json(false)
, enable_protobuf_map(true) {
, enable_protobuf_map(true)
#ifdef BAIDU_INTERNAL
, bytes_to_base64(false) {
#else
, bytes_to_base64(true) {
#endif
}
class PbToJsonConverter {
......@@ -175,13 +181,27 @@ bool PbToJsonConverter::_PbFieldToJson(
for (int index = 0; index < field_size; ++index) {
value = reflection->GetRepeatedStringReference(
message, field, index, &value);
handler.String(value.data(), value.size(), false);
if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES
&& _option.bytes_to_base64) {
std::string value_decoded;
base::Base64Encode(value, &value_decoded);
handler.String(value_decoded.data(), value_decoded.size(), false);
} else {
handler.String(value.data(), value.size(), false);
}
}
handler.EndArray(field_size);
} else {
value = reflection->GetStringReference(message, field, &value);
handler.String(value.data(), value.size(), false);
if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES
&& _option.bytes_to_base64) {
std::string value_decoded;
base::Base64Encode(value, &value_decoded);
handler.String(value_decoded.data(), value_decoded.size(), false);
} else {
handler.String(value.data(), value.size(), false);
}
}
break;
}
......
......@@ -28,12 +28,18 @@ struct Pb2JsonOptions {
// Use rapidjson::PrettyWriter to generate the json when this option is on.
// NOTE: currently PrettyWriter is not optimized yet thus the conversion
// functions may be slower when this option is turned on.
// Default: false
bool pretty_json;
// true, we will automatically convert
// "repeated { required string key = 1; required string value = 2; }"
// to a map object of json and vice versa
// Convert "repeated { required string key = 1; required string value = 2; }"
// to a map object of json and vice versa when this option is turned on.
// Default: true
bool enable_protobuf_map;
// Encode the field of type bytes to string in json using base64
// encoding when this option is turned on.
// Default: false for baidu-internal, true otherwise.
bool bytes_to_base64;
};
// Rules: http://wiki.baidu.com/display/RPC/Json+%3C%3D%3E+Protobuf
......
......@@ -133,6 +133,7 @@ TEST_BASE_SOURCES = \
test_file_util_linux.cc \
base_unittest_main.cpp
TEST_BASE_OBJS = $(addsuffix .o, $(basename $(TEST_BASE_SOURCES)))
TEST_BVAR_SOURCES = $(wildcard bvar_*_unittest.cpp)
......
package addressbook;
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
optional int64 data = 5;
optional sint32 data32 = 6;
optional sint64 data64 = 7;
required double datadouble = 8;
required float datafloat = 9;
optional uint32 datau32 = 10;
optional uint64 datau64 = 11;
optional bool databool = 12;
optional bytes databyte = 13;
optional fixed32 datafix32 = 14;
optional fixed64 datafix64 = 15;
optional sfixed32 datasfix32 = 16;
optional sfixed64 datasfix64 = 17;
optional float datafloat_scientific = 18;
optional double datadouble_scientific = 19;
extensions 100 to 200;
}
extend Person {
optional string hobby = 100;
}
message AddressBook {
repeated Person person = 1;
}
message Ext {
optional fixed32 age = 2;
required bytes databyte = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
optional PhoneType enumtype = 4 [default = HOME];
}
message Content {
optional string uid = 1;
required float distance = 16;
optional Ext ext = 17;
}
message JsonContextBody {
optional int64 type = 1;
repeated int32 data = 5;
repeated string info = 6;
required bool judge = 2;
required double spur = 3;
repeated Content content = 4;
optional float text = 7;
}
message PersonInfo {
optional string name = 1;
optional int32 id = 2; // Unique ID number for this person.
optional JsonContextBody json_body = 18;
}
message AddressBook {
repeated PersonInfo person = 1;
}
message ExtEncDec {
optional fixed32 Aa_ge_Z040_ = 2;
optional bytes databyte_Z040_std_Z058__Z058_string_Z041_ = 3;
enum PhoneTypeEncDec {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
optional PhoneTypeEncDec enum_Z045__Z045_type = 4 [default = HOME];
}
message ContentEncDec {
optional string uid_Z042_ = 1;
required float Distance_info_ = 16;
optional ExtEncDec _ext_Z037_T_ = 17;
}
message JsonContextBodyEncDec {
repeated string info = 6;
optional int64 type = 1;
repeated int32 data_Z058_array = 5;
required bool judge = 2;
optional double spur = 3;
repeated ContentEncDec _Z064_Content_Test_Z037__Z064_ = 4;
}
message PersonEncDec {
optional string name = 1;
optional int32 id = 2; // Unique ID number for this person.
optional JsonContextBodyEncDec json_body = 18;
}
message AddressBookEncDec {
repeated PersonEncDec person = 1;
}
message AddressNoMap {
required string addr = 1;
}
message AddressIntMap {
required string addr = 1;
message MapFieldEntry {
required string key = 1;
required int32 value = 2;
}
repeated MapFieldEntry numbers = 2;
}
message AddressStringMap {
required string addr = 1;
message MapFieldEntry {
required string key = 1;
required string value = 2;
}
repeated MapFieldEntry contacts = 2;
}
message AddressComplex {
required string addr = 1;
message FriendEntry {
required string key = 1;
message Education {
required string school = 1;
required int32 year = 2;
}
repeated Education value = 2;
}
repeated FriendEntry friends = 2;
}
message haha {
repeated int32 a = 1;
}
\ No newline at end of file
// See README.txt for information and build instructions.
#include <sys/time.h>
#include <gtest/gtest.h>
#include <iostream>
#include <fstream>
#include <string>
#include <gperftools/profiler.h>
#include <json2pb/pb_to_json.h>
#include <json2pb/json_to_pb.h>
#include <base/iobuf.h>
#include <google/protobuf/text_format.h>
#include <base/third_party/rapidjson/rapidjson.h>
#include "base/time.h"
#include "message.pb.h"
#include "addressbook1.pb.h"
#include "addressbook.pb.h"
#include "addressbook_encode_decode.pb.h"
#include "addressbook_map.pb.h"
#include <json2pb/encode_decode.h>
namespace { // just for coding-style check
using addressbook::AddressBook;
using addressbook::Person;
class ProtobufJsonTest : public testing::Test {
protected:
void SetUp() {}
void TearDown() {}
};
inline int64_t gettimeofday_us() {
timeval now;
gettimeofday(&now, NULL);
return now.tv_sec * 1000000L + now.tv_usec;
}
TEST_F(ProtobufJsonTest, json_to_pb_normal_case) {
const int N = 1000;
int64_t total_tm = 0;
int64_t total_tm2 = 0;
for (int i = 0; i < N; ++i) {
std::string info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\"ext\":"
"{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},"
"\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,"
"\"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZQ==\","
"\"enumtype\":2},\"uid\":\"someone0\"}], \"judge\":false,"
"\"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}";
std::string error;
JsonContextBody data;
const int64_t tm1 = gettimeofday_us();
const bool ret = json2pb::JsonToProtoMessage(info3, &data, &error);
const int64_t tm2 = gettimeofday_us();
total_tm += tm2 - tm1;
ASSERT_TRUE(ret);
std::string info4;
std::string error1;
const int64_t tm3 = gettimeofday_us();
bool ret2 = json2pb::ProtoMessageToJson(data, &info4, &error1);
const int64_t tm4 = gettimeofday_us();
ASSERT_TRUE(ret2);
total_tm2 += tm4 - tm3;
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"data\":[1,2,3,4,5,6,7,8,9,10],"
"\"judge\":false,\"spur\":2.0,\"content\":[{\"uid\":\"someone\","
"\"distance\":1.0,\"ext\":{\"age\":1666666666,\"databyte\":\"d2VsY29tZQ==\","
"\"enumtype\":\"HOME\"}},\{\"uid\":\"someone0\",\"distance\":10.0,\"ext\":"
"{\"age\":1666666660,\"databyte\":\"d2VsY29tZQ==\",\"enumtype\":\"WORK\"}}]}",
info4.data());
#else
ASSERT_STREQ("{\"data\":[1,2,3,4,5,6,7,8,9,10],"
"\"judge\":false,\"spur\":2,\"content\":[{\"uid\":\"someone\","
"\"distance\":1,\"ext\":{\"age\":1666666666,\"databyte\":\"d2VsY29tZQ==\","
"\"enumtype\":\"HOME\"}},\{\"uid\":\"someone0\",\"distance\":10,\"ext\":"
"{\"age\":1666666660,\"databyte\":\"d2VsY29tZQ==\",\"enumtype\":\"WORK\"}}]}",
info4.data());
#endif
}
std::cout << "json2pb=" << total_tm / N
<< "us pb2json=" << total_tm2 / N << "us"
<< std::endl;
}
TEST_F(ProtobufJsonTest, json_base64_string_to_pb_types_case) {
std::string info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\"ext\":"
"{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},"
"\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,"
"\"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZTA=\","
"\"enumtype\":2},\"uid\":\"someone0\"}], \"judge\":false,"
"\"spur\":2}";
std::string error;
JsonContextBody data;
json2pb::Json2PbOptions options_j2pb;
options_j2pb.base64_to_bytes = true;
const bool ret = json2pb::JsonToProtoMessage(info3, &data, options_j2pb, &error);
ASSERT_TRUE(ret);
ASSERT_TRUE(data.content_size() == 2);
ASSERT_EQ(data.content(0).ext().databyte(), "welcome");
ASSERT_EQ(data.content(1).ext().databyte(), "welcome0");
std::string info4;
std::string error1;
json2pb::Pb2JsonOptions options_pb2j;
options_pb2j.bytes_to_base64 = true;
bool ret2 = json2pb::ProtoMessageToJson(data, &info4, options_pb2j, &error1);
ASSERT_TRUE(ret2);
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"judge\":false,\"spur\":2.0,\"content\":[{\"uid\":\"someone\","
"\"distance\":1.0,\"ext\":{\"age\":1666666666,\"databyte\":\"d2VsY29tZQ==\","
"\"enumtype\":\"HOME\"}},\{\"uid\":\"someone0\",\"distance\":10.0,\"ext\":"
"{\"age\":1666666660,\"databyte\":\"d2VsY29tZTA=\",\"enumtype\":\"WORK\"}}]}",
info4.data());
#else
ASSERT_STREQ("{\"judge\":false,\"spur\":2,\"content\":[{\"uid\":\"someone\","
"\"distance\":1,\"ext\":{\"age\":1666666666,\"databyte\":\"d2VsY29tZQ==\","
"\"enumtype\":\"HOME\"}},\{\"uid\":\"someone0\",\"distance\":10,\"ext\":"
"{\"age\":1666666660,\"databyte\":\"d2VsY29tZTA=\",\"enumtype\":\"WORK\"}}]}",
info4.data());
#endif
}
TEST_F(ProtobufJsonTest, json_to_pb_map_case) {
std::string json = "{\"addr\":\"baidu.com\","
"\"numbers\":{\"tel\":123456,\"cell\":654321},"
"\"contacts\":{\"email\":\"frank@baidu.com\","
" \"office\":\"Shanghai\"},"
"\"friends\":{\"John\":[{\"school\":\"SJTU\",\"year\":2007}]}}";
std::string error;
AddressNoMap ab1;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab1, &error));
ASSERT_EQ("baidu.com", ab1.addr());
AddressIntMap ab2;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab2, &error));
ASSERT_EQ("baidu.com", ab2.addr());
ASSERT_EQ("tel", ab2.numbers(0).key());
ASSERT_EQ(123456, ab2.numbers(0).value());
ASSERT_EQ("cell", ab2.numbers(1).key());
ASSERT_EQ(654321, ab2.numbers(1).value());
AddressStringMap ab3;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab3, &error));
ASSERT_EQ("baidu.com", ab3.addr());
ASSERT_EQ("email", ab3.contacts(0).key());
ASSERT_EQ("frank@baidu.com", ab3.contacts(0).value());
ASSERT_EQ("office", ab3.contacts(1).key());
ASSERT_EQ("Shanghai", ab3.contacts(1).value());
AddressComplex ab4;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab4, &error)) << error;
ASSERT_EQ("baidu.com", ab4.addr());
ASSERT_EQ("John", ab4.friends(0).key());
ASSERT_EQ("SJTU", ab4.friends(0).value(0).school());
ASSERT_EQ(2007, ab4.friends(0).value(0).year());
std::string old_json = "{\"addr\":\"baidu.com\","
"\"numbers\":[{\"key\":\"tel\",\"value\":123456},"
" {\"key\":\"cell\",\"value\":654321}]}";
ab2.Clear();
ASSERT_TRUE(json2pb::JsonToProtoMessage(old_json, &ab2, &error)) << error;
ASSERT_EQ("baidu.com", ab2.addr());
ASSERT_EQ("tel", ab2.numbers(0).key());
ASSERT_EQ(123456, ab2.numbers(0).value());
ASSERT_EQ("cell", ab2.numbers(1).key());
ASSERT_EQ(654321, ab2.numbers(1).value());
}
TEST_F(ProtobufJsonTest, json_to_pb_encode_decode) {
std::string info3 = "{\"@Content_Test%@\":[{\"Distance_info_\":1,\
\"_ext%T_\":{\"Aa_ge(\":1666666666, \"databyte(std::string)\":\
\"d2VsY29tZQ==\", \"enum--type\":\"HOME\"},\"uid*\":\"welcome\"}], \
\"judge\":false, \"spur\":2, \"data:array\":[]}";
printf("----------test json to pb------------\n\n");
std::string error;
JsonContextBodyEncDec data;
ASSERT_TRUE(json2pb::JsonToProtoMessage(info3, &data, &error));
std::string info4;
std::string error1;
ASSERT_TRUE(json2pb::ProtoMessageToJson(data, &info4, &error1));
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"judge\":false,\"spur\":2.0,"
"\"@Content_Test%@\":[{\"uid*\":\"welcome\",\"Distance_info_\":1.0,"
"\"_ext%T_\":{\"Aa_ge(\":1666666666,\"databyte(std::string)\":\"d2VsY29tZQ==\","
"\"enum--type\":\"HOME\"}}]}", info4.data());
#else
ASSERT_STREQ("{\"judge\":false,\"spur\":2,"
"\"@Content_Test%@\":[{\"uid*\":\"welcome\",\"Distance_info_\":1,"
"\"_ext%T_\":{\"Aa_ge(\":1666666666,\"databyte(std::string)\":\"d2VsY29tZQ==\","
"\"enum--type\":\"HOME\"}}]}", info4.data());
#endif
}
TEST_F(ProtobufJsonTest, json_to_pb_unicode_case) {
AddressBook address_book;
Person* person = address_book.add_person();
person->set_id(100);
char name[255 * 1024];
for (int j = 0; j < 255; j++) {
for (int i = 0; i < 1024; i++) {
name[j*1024 + i] = i + 1;
}
}
name[255 * 1024 - 1] = '\0';
person->set_name(name);
person->set_data(-240000000);
person->set_data32(6);
person->set_data64(-1820000000);
person->set_datadouble(123.456);
person->set_datadouble_scientific(1.23456789e+08);
person->set_datafloat_scientific(1.23456789e+08);
person->set_datafloat(8.6123);
person->set_datau32(60);
person->set_datau64(960);
person->set_databool(0);
person->set_databyte("welcome to china");
person->set_datafix32(1);
person->set_datafix64(666);
person->set_datasfix32(120);
person->set_datasfix64(-802);
std::string info1;
std::string error;
google::protobuf::TextFormat::Printer printer;
std::string text;
printer.PrintToString(*person, &text);
printf("----------test pb to json------------\n\n");
bool ret = json2pb::ProtoMessageToJson(address_book, &info1, &error);
ASSERT_TRUE(ret);
AddressBook address_book_test;
ret = json2pb::JsonToProtoMessage(info1, &address_book_test, &error);
ASSERT_TRUE(ret);
std::string info2;
ret = json2pb::ProtoMessageToJson(address_book_test, &info2, &error);
ASSERT_TRUE(ret);
ASSERT_TRUE(!info1.compare(info2));
base::IOBuf buf;
base::IOBufAsZeroCopyOutputStream stream(&buf);
bool res = json2pb::ProtoMessageToJson(address_book, &stream, NULL);
ASSERT_TRUE(res);
base::IOBufAsZeroCopyInputStream stream2(buf);
AddressBook address_book_test3;
ret = json2pb::JsonToProtoMessage(&stream2, &address_book_test3, &error);
ASSERT_TRUE(ret);
std::string info3;
ret = json2pb::ProtoMessageToJson(address_book_test3, &info3, &error);
ASSERT_TRUE(ret);
ASSERT_TRUE(!info2.compare(info3));
}
TEST_F(ProtobufJsonTest, json_to_pb_edge_case) {
std::string info3 = "{\"judge\":false, \"spur\":2.0e1}";
std::string error;
JsonContextBody data;
bool ret = json2pb::JsonToProtoMessage(info3, &data, &error);
ASSERT_TRUE(ret);
std::string info4;
std::string error1;
ret = json2pb::ProtoMessageToJson(data, &info4, &error1);
ASSERT_TRUE(ret);
info3 = "{\"judge\":false, \"spur\":-2, \"data\":[], \"info\":[],\"content\":[]}";
error.clear();
JsonContextBody data1;
ret = json2pb::JsonToProtoMessage(info3, &data1, &error);
ASSERT_TRUE(ret);
info4.clear();
error1.clear();
ret = json2pb::ProtoMessageToJson(data1, &info4, &error1);
ASSERT_TRUE(ret);
info3 = "{\"judge\":false, \"spur\":\"NaN\"}";
error.clear();
JsonContextBody data2;
ret = json2pb::JsonToProtoMessage(info3, &data2, &error);
ASSERT_TRUE(ret);
info4.clear();
error1.clear();
ret = json2pb::ProtoMessageToJson(data2, &info4, &error1);
ASSERT_TRUE(ret);
info3 = "{\"judge\":false, \"spur\":\"Infinity\"}";
error.clear();
JsonContextBody data3;
ret = json2pb::JsonToProtoMessage(info3, &data3, &error);
ASSERT_TRUE(ret);
info4.clear();
error1.clear();
ret = json2pb::ProtoMessageToJson(data3, &info4, &error1);
ASSERT_TRUE(ret);
info3 = "{\"judge\":false, \"spur\":\"-inFiNITY\"}";
error.clear();
JsonContextBody data4;
ret = json2pb::JsonToProtoMessage(info3, &data4, &error);
ASSERT_TRUE(ret);
info4.clear();
error1.clear();
ret = json2pb::ProtoMessageToJson(data4, &info4, &error1);
ASSERT_TRUE(ret);
info3 = "{\"judge\":false, \"spur\":2.0, \"content\":[{\"distance\":2.5, "
"\"ext\":{\"databyte\":\"d2VsY29tZQ==\", \"enumtype\":\"MOBILE\"}}]}";
error.clear();
JsonContextBody data5;
ret = json2pb::JsonToProtoMessage(info3, &data5, &error);
ASSERT_TRUE(ret);
info4.clear();
error1.clear();
ret = json2pb::ProtoMessageToJson(data5, &info4, &error1);
ASSERT_TRUE(ret);
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\
\"ext\":{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},\
\"uid\":\"someone\"},{\"distance\":2.3,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":\"Test\"},\
\"uid\":\"someone0\"}], \"judge\":false, \
\"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}";
error.clear();
JsonContextBody data9;
ret = json2pb::JsonToProtoMessage(info3, &data9, &error);
ASSERT_TRUE(ret);
ASSERT_STREQ("Invalid value `\"Test\"' for optional field `Ext.enumtype' which SHOULD be enum", error.data());
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\
\"ext\":{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},\
\"uid\":\"someone\"},{\"distance\":5,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":15},\
\"uid\":\"someone0\"}], \"judge\":false, \
\"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}";
error.clear();
JsonContextBody data10;
ret = json2pb::JsonToProtoMessage(info3, &data10, &error);
ASSERT_TRUE(ret);
ASSERT_STREQ("Invalid value `15' for optional field `Ext.enumtype' which SHOULD be enum", error.data());
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\
\"ext\":{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},\
\"uid\":\"someone\"},{\"distance\":5,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":15},\
\"uid\":\"someone0\"}], \"judge\":false, \
\"spur\":2, \"type\":[\"123\"]}";
error.clear();
JsonContextBody data11;
ret = json2pb::JsonToProtoMessage(info3, &data11, &error);
ASSERT_TRUE(ret);
ASSERT_STREQ("Invalid value `array' for optional field `JsonContextBody.type' which SHOULD be INT64, Invalid value `15' for optional field `Ext.enumtype' which SHOULD be enum",
error.data());
}
TEST_F(ProtobufJsonTest, json_to_pb_expected_failed_case) {
std::string info3 = "{\"content\":[{\"unknown_member\":2,\"ext\":{\"age\":1666666666, \
\"databyte\":\"welcome\", \"enumtype\":1},\"uid\":\"someone\"},\
{\"unknown_member\":20,\"ext\":{\"age\":1666666660, \"databyte\":\
\"welcome0\", \"enumtype\":2},\"uid\":\"someone0\"}], \
\"judge\":false, \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}";
std::string error;
JsonContextBody data;
bool ret = json2pb::JsonToProtoMessage(info3, &data, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Missing required field: Content.distance", error.data());
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\"ext\":{\"age\":1666666666, \
\"enumtype\":1},\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\
\"uid\":\"someone0\"}], \"judge\":false, \
\"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}";
error.clear();
JsonContextBody data2;
ret = json2pb::JsonToProtoMessage(info3, &data2, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Missing required field: Ext.databyte", error.data());
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\
\"ext\":{\"age\":1666666666, \"databyte\":\"welcome\", \"enumtype\":1},\
\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\
\"uid\":\"someone0\"}], \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}";
error.clear();
JsonContextBody data3;
ret = json2pb::JsonToProtoMessage(info3, &data, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Missing required field: JsonContextBody.judge", error.data());
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\
\"ext\":{\"age\":1666666666, \"databyte\":\"welcome\", \"enumtype\":1},\
\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\
\"uid\":\"someone0\"}], \"judge\":\"false\", \
\"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}";
error.clear();
JsonContextBody data4;
ret = json2pb::JsonToProtoMessage(info3, &data4, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Invalid value `\"false\"' for field `JsonContextBody.judge' which SHOULD be BOOL", error.data());
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\
\"ext\":{\"age\":1666666666, \"databyte\":\"welcome\", \"enumtype\":1},\
\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\
\"uid\":\"someone0\"}], \"judge\":false, \
\"spur\":2, \"data\":[\"1\",\"2\",\"3\",\"4\"]}";
error.clear();
JsonContextBody data5;
ret = json2pb::JsonToProtoMessage(info3, &data5, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Invalid value `\"1\"' for field `JsonContextBody.data' which SHOULD be INT32", error.data());
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\
\"ext\":{\"age\":1666666666, \"databyte\":\"welcome\", \"enumtype\":1},\
\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\
\"uid\":\"someone0\"}], \"judge\":false, \
\"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10], \"info\":2}";
error.clear();
JsonContextBody data6;
ret = json2pb::JsonToProtoMessage(info3, &data6, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Invalid value for repeated field: JsonContextBody.info", error.data());
info3 = "{\"judge\":false, \"spur\":\"NaNa\"}";
error.clear();
JsonContextBody data7;
ret = json2pb::JsonToProtoMessage(info3, &data7, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Invalid value `\"NaNa\"' for field `JsonContextBody.spur' which SHOULD be d",
error.data());
info3 = "{\"judge\":false, \"spur\":\"Infinty\"}";
error.clear();
JsonContextBody data8;
ret = json2pb::JsonToProtoMessage(info3, &data8, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Invalid value `\"Infinty\"' for field `JsonContextBody.spur' which SHOULD be d",
error.data());
info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\"ext\":{\"age\":1666666666, \
\"enumtype\":1},\"uid\":23},{\"distance\":10,\"unknown_member\":20,\
\"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\
\"uid\":\"someone0\"}], \"judge\":false, \
\"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}";
error.clear();
JsonContextBody data9;
ret = json2pb::JsonToProtoMessage(info3, &data9, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Invalid value `23' for optional field `Content.uid' which SHOULD be string, Missing required field: Ext.databyte", error.data());
}
TEST_F(ProtobufJsonTest, json_to_pb_perf_case) {
std::string info3 = "{\"content\":[{\"distance\":1.0,\
\"ext\":{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},\
\"uid\":\"welcome\"}], \"judge\":false, \"spur\":2.0, \"data\":[]}";
printf("----------test json to pb performance------------\n\n");
std::string error;
ProfilerStart("json_to_pb_perf.prof");
base::Timer timer;
bool res;
float avg_time1 = 0;
float avg_time2 = 0;
const int times = 100000;
for (int i = 0; i < times; i++) {
JsonContextBody data;
timer.start();
res = json2pb::JsonToProtoMessage(info3, &data, &error);
timer.stop();
avg_time1 += timer.u_elapsed();
ASSERT_TRUE(res);
std::string info4;
std::string error1;
timer.start();
res = json2pb::ProtoMessageToJson(data, &info4, &error1);
timer.stop();
avg_time2 += timer.u_elapsed();
ASSERT_TRUE(res);
}
avg_time1 /= times;
avg_time2 /= times;
ProfilerStop();
printf("avg time to convert json to pb is %fus\n", avg_time1);
printf("avg time to convert pb to json is %fus\n", avg_time2);
}
TEST_F(ProtobufJsonTest, json_to_pb_encode_decode_perf_case) {
std::string info3 = "{\"@Content_Test%@\":[{\"Distance_info_\":1,\
\"_ext%T_\":{\"Aa_ge(\":1666666666, \"databyte(std::string)\":\
\"welcome\", \"enum--type\":1},\"uid*\":\"welcome\"}], \
\"judge\":false, \"spur\":2, \"data:array\":[]}";
printf("----------test json to pb encode/decode performance------------\n\n");
std::string error;
ProfilerStart("json_to_pb_encode_decode_perf.prof");
base::Timer timer;
bool res;
float avg_time1 = 0;
float avg_time2 = 0;
const int times = 100000;
for (int i = 0; i < times; i++) {
JsonContextBody data;
timer.start();
res = json2pb::JsonToProtoMessage(info3, &data, &error);
timer.stop();
avg_time1 += timer.u_elapsed();
ASSERT_TRUE(res);
std::string info4;
std::string error1;
timer.start();
res = json2pb::ProtoMessageToJson(data, &info4, &error1);
timer.stop();
avg_time2 += timer.u_elapsed();
ASSERT_TRUE(res);
}
avg_time1 /= times;
avg_time2 /= times;
ProfilerStop();
printf("avg time to convert json to pb is %fus\n", avg_time1);
printf("avg time to convert pb to json is %fus\n", avg_time2);
}
TEST_F(ProtobufJsonTest, json_to_pb_complex_perf_case) {
std::ifstream in("jsonout", std::ios::in);
std::ostringstream tmp;
tmp << in.rdbuf();
base::IOBuf buf;
buf.append(tmp.str());
in.close();
printf("----------test json to pb performance------------\n\n");
std::string error;
base::Timer timer;
bool res;
float avg_time1 = 0;
const int times = 10000;
json2pb::Json2PbOptions options;
options.base64_to_bytes = false;
ProfilerStart("json_to_pb_complex_perf.prof");
for (int i = 0; i < times; i++) {
gss::message::gss_us_res_t data;
base::IOBufAsZeroCopyInputStream stream(buf);
timer.start();
res = json2pb::JsonToProtoMessage(&stream, &data, options, &error);
timer.stop();
avg_time1 += timer.u_elapsed();
ASSERT_TRUE(res);
}
ProfilerStop();
avg_time1 /= times;
printf("avg time to convert json to pb is %fus\n", avg_time1);
}
TEST_F(ProtobufJsonTest, json_to_pb_to_string_complex_perf_case) {
std::ifstream in("jsonout", std::ios::in);
std::ostringstream tmp;
tmp << in.rdbuf();
std::string info3 = tmp.str();
in.close();
printf("----------test json to pb performance------------\n\n");
std::string error;
base::Timer timer;
bool res;
float avg_time1 = 0;
const int times = 10000;
json2pb::Json2PbOptions options;
options.base64_to_bytes = false;
ProfilerStart("json_to_pb_to_string_complex_perf.prof");
for (int i = 0; i < times; i++) {
gss::message::gss_us_res_t data;
timer.start();
res = json2pb::JsonToProtoMessage(info3, &data, options, &error);
timer.stop();
avg_time1 += timer.u_elapsed();
ASSERT_TRUE(res);
}
avg_time1 /= times;
ProfilerStop();
printf("avg time to convert json to pb is %fus\n", avg_time1);
}
TEST_F(ProtobufJsonTest, pb_to_json_normal_case) {
AddressBook address_book;
Person* person = address_book.add_person();
person->set_id(100);
person->set_name("baidu");
person->set_email("welcome@baidu.com");
Person::PhoneNumber* phone_number = person->add_phone();
phone_number->set_number("number123");
phone_number->set_type(Person::HOME);
person->set_data(-240000000);
person->set_data32(6);
person->set_data64(-1820000000);
person->set_datadouble(123.456);
person->set_datadouble_scientific(1.23456789e+08);
person->set_datafloat_scientific(1.23456789e+08);
person->set_datafloat(8.6123);
person->set_datau32(60);
person->set_datau64(960);
person->set_databool(0);
person->set_databyte("welcome");
person->set_datafix32(1);
person->set_datafix64(666);
person->set_datasfix32(120);
person->set_datasfix64(-802);
std::string info1;
google::protobuf::TextFormat::Printer printer;
std::string text;
printer.PrintToString(*person, &text);
printf("text:%s\n", text.data());
printf("----------test pb to json------------\n\n");
json2pb::Pb2JsonOptions option;
option.bytes_to_base64 = true;
bool ret = json2pb::ProtoMessageToJson(address_book, &info1, option, NULL);
ASSERT_TRUE(ret);
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960,"
"\"databool\":false,\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,"
"\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802,"
"\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}",
info1.data());
#else
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false,"
"\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,\"datafix64\":666,"
"\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792,"
"\"datadouble_scientific\":123456789}]}", info1.data());
#endif
info1.clear();
{
json2pb::Pb2JsonOptions option;
option.bytes_to_base64 = true;
ret = ProtoMessageToJson(address_book, &info1, option, NULL);
}
ASSERT_TRUE(ret);
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960,"
"\"databool\":false,\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,"
"\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802,"
"\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}",
info1.data());
#else
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false,"
"\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,\"datafix64\":666,"
"\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792,"
"\"datadouble_scientific\":123456789}]}", info1.data());
#endif
info1.clear();
{
json2pb::Pb2JsonOptions option;
option.bytes_to_base64 = true;
option.enum_option = json2pb::OUTPUT_ENUM_BY_NUMBER;
ret = ProtoMessageToJson(address_book, &info1, option, NULL);
}
ASSERT_TRUE(ret);
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":1}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960,"
"\"databool\":false,\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,"
"\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802,"
"\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}",
info1.data());
#else
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":1}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false,"
"\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,\"datafix64\":666,"
"\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792,"
"\"datadouble_scientific\":123456789}]}", info1.data());
#endif
printf("----------test json to pb------------\n\n");
const int N = 1000;
int64_t total_tm = 0;
int64_t total_tm2 = 0;
for (int i = 0; i < N; ++i) {
std::string info3;
AddressBook data1;
std::string error1;
const int64_t tm1 = gettimeofday_us();
bool ret1 = json2pb::JsonToProtoMessage(info1, &data1, &error1);
const int64_t tm2 = gettimeofday_us();
total_tm += tm2 - tm1;
ASSERT_TRUE(ret1);
std::string error2;
const int64_t tm3 = gettimeofday_us();
ret1 = json2pb::ProtoMessageToJson(data1, &info3, &error2);
const int64_t tm4 = gettimeofday_us();
ASSERT_TRUE(ret1);
total_tm2 += tm4 - tm3;
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960,"
"\"databool\":false,\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,"
"\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802,"
"\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}",
info3.data());
#else
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false,"
"\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,\"datafix64\":666,"
"\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792,"
"\"datadouble_scientific\":123456789}]}", info3.data());
#endif
}
std::cout << "json2pb=" << total_tm / N
<< "us pb2json=" << total_tm2 / N << "us"
<< std::endl;
}
TEST_F(ProtobufJsonTest, pb_to_json_map_case) {
std::string json = "{\"addr\":\"baidu.com\","
"\"numbers\":{\"tel\":123456,\"cell\":654321},"
"\"contacts\":{\"email\":\"frank@baidu.com\","
" \"office\":\"Shanghai\"},"
"\"friends\":{\"John\":[{\"school\":\"SJTU\",\"year\":2007}]}}";
std::string output;
std::string error;
AddressNoMap ab1;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab1, &error));
ASSERT_TRUE(json2pb::ProtoMessageToJson(ab1, &output, &error));
ASSERT_TRUE(output.find("\"addr\":\"baidu.com\"") != std::string::npos);
output.clear();
AddressIntMap ab2;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab2, &error));
ASSERT_TRUE(json2pb::ProtoMessageToJson(ab2, &output, &error));
ASSERT_TRUE(output.find("\"addr\":\"baidu.com\"") != std::string::npos);
ASSERT_TRUE(output.find("\"tel\":123456") != std::string::npos);
ASSERT_TRUE(output.find("\"cell\":654321") != std::string::npos);
output.clear();
AddressStringMap ab3;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab3, &error));
ASSERT_TRUE(json2pb::ProtoMessageToJson(ab3, &output, &error));
ASSERT_TRUE(output.find("\"addr\":\"baidu.com\"") != std::string::npos);
ASSERT_TRUE(output.find("\"email\":\"frank@baidu.com\"") != std::string::npos);
ASSERT_TRUE(output.find("\"office\":\"Shanghai\"") != std::string::npos);
output.clear();
AddressComplex ab4;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab4, &error));
ASSERT_TRUE(json2pb::ProtoMessageToJson(ab4, &output, &error));
ASSERT_TRUE(output.find("\"addr\":\"baidu.com\"") != std::string::npos);
ASSERT_TRUE(output.find("\"friends\":{\"John\":[{\"school\":\"SJTU\","
"\"year\":2007}]}") != std::string::npos);
}
TEST_F(ProtobufJsonTest, pb_to_json_encode_decode) {
JsonContextBodyEncDec json_data;
json_data.set_type(80000);
json_data.add_data_z058_array(200);
json_data.add_data_z058_array(300);
json_data.add_info("this is json data's info");
json_data.add_info("this is a test");
json_data.set_judge(true);
json_data.set_spur(3.45);
ContentEncDec * content = json_data.add__z064_content_test_z037__z064_();
content->set_uid_z042_("content info");
content->set_distance_info_(1234.56);
ExtEncDec* ext = content->mutable__ext_z037_t_();
ext->set_aa_ge_z040_(160000);
ext->set_databyte_z040_std_z058__z058_string_z041_("databyte");
ext->set_enum_z045__z045_type(ExtEncDec_PhoneTypeEncDec_WORK);
std::string info1;
google::protobuf::TextFormat::Printer printer;
std::string text;
printer.PrintToString(json_data, &text);
printf("text:%s\n", text.data());
printf("----------test pb to json------------\n\n");
json2pb::Pb2JsonOptions option;
option.bytes_to_base64 = true;
ASSERT_TRUE(ProtoMessageToJson(json_data, &info1, option, NULL));
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000,"
"\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":"
"[{\"uid*\":\"content info\",\"Distance_info_\":1234.56005859375,\"_ext%T_\":"
"{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\","
"\"enum--type\":\"WORK\"}}]}",
info1.data());
#else
ASSERT_STREQ("{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000,"
"\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":"
"[{\"uid*\":\"content info\",\"Distance_info_\":1234.560059,\"_ext%T_\":"
"{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\","
"\"enum--type\":\"WORK\"}}]}",
info1.data());
#endif
printf("----------test json to pb------------\n\n");
std::string info3;
JsonContextBody data1;
json2pb::JsonToProtoMessage(info1, &data1, NULL);
json2pb::ProtoMessageToJson(data1, &info3, NULL);
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000,"
"\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":"
"[{\"uid*\":\"content info\",\"Distance_info_\":1234.56005859375,\"_ext%T_\":"
"{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\","
"\"enum--type\":\"WORK\"}}]}",
info1.data());
#else
ASSERT_STREQ("{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000,"
"\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":"
"[{\"uid*\":\"content info\",\"Distance_info_\":1234.560059,\"_ext%T_\":"
"{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\","
"\"enum--type\":\"WORK\"}}]}",
info1.data());
#endif
}
TEST_F(ProtobufJsonTest, pb_to_json_control_char_case) {
AddressBook address_book;
Person* person = address_book.add_person();
person->set_id(100);
char ch = 0x01;
char* name = new char[17];
memcpy(name, "baidu ", 6);
name[6] = ch;
char c = 0x08;
char t = 0x1A;
memcpy(name + 7, "test", 4);
name[11] = c;
name[12] = t;
memcpy(name + 13, "end", 3);
name[16] = '\0';
person->set_name(name);
printf("name is %s\n", name);
person->set_email("welcome@baidu.com");
Person::PhoneNumber* phone_number = person->add_phone();
phone_number->set_number("number123");
phone_number->set_type(Person::HOME);
person->set_data(-240000000);
person->set_data32(6);
person->set_data64(-1820000000);
person->set_datadouble(123.456);
person->set_datadouble_scientific(1.23456789e+08);
person->set_datafloat_scientific(1.23456789e+08);
person->set_datafloat(8.6123);
person->set_datau32(60);
person->set_datau64(960);
person->set_databool(0);
person->set_databyte("welcome to china");
person->set_datafix32(1);
person->set_datafix64(666);
person->set_datasfix32(120);
person->set_datasfix64(-802);
std::string info1;
google::protobuf::TextFormat::Printer printer;
std::string text;
printer.PrintToString(*person, &text);
printf("text:%s\n", text.data());
bool ret = false;
printf("----------test pb to json------------\n\n");
{
json2pb::Pb2JsonOptions option;
option.bytes_to_base64 = false;
ret = ProtoMessageToJson(address_book, &info1, option, NULL);
ASSERT_TRUE(ret);
}
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":"
"\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960,"
"\"databool\":false,\"databyte\":\"welcome to china\",\"datafix32\":1,"
"\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802,"
"\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}",
info1.data());
#else
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":"
"\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false,"
"\"databyte\":\"welcome to china\",\"datafix32\":1,\"datafix64\":666,"
"\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792,"
"\"datadouble_scientific\":123456789}]}", info1.data());
#endif
info1.clear();
{
json2pb::Pb2JsonOptions option;
option.bytes_to_base64 = true;
ret = ProtoMessageToJson(address_book, &info1, option, NULL);
ASSERT_TRUE(ret);
}
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":"
"\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960,"
"\"databool\":false,\"databyte\":\"d2VsY29tZSB0byBjaGluYQ==\",\"datafix32\":1,"
"\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802,"
"\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}",
info1.data());
#else
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":"
"\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false,"
"\"databyte\":\"d2VsY29tZSB0byBjaGluYQ==\",\"datafix32\":1,\"datafix64\":666,"
"\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792,"
"\"datadouble_scientific\":123456789}]}", info1.data());
#endif
info1.clear();
{
json2pb::Pb2JsonOptions option;
option.enum_option = json2pb::OUTPUT_ENUM_BY_NUMBER;
option.bytes_to_base64 = false;
ret = ProtoMessageToJson(address_book, &info1, option, NULL);
ASSERT_TRUE(ret);
}
#ifndef RAPIDJSON_VERSION_0_1
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":"
"\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":1}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960,"
"\"databool\":false,\"databyte\":\"welcome to china\",\"datafix32\":1,"
"\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802,"
"\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}",
info1.data());
#else
std::cout << info1.data() << std::endl;
ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":"
"\"welcome@baidu.com\","
"\"phone\":[{\"number\":\"number123\",\"type\":1}],\"data\":-240000000,"
"\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456,"
"\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,"
"\"databool\":false,\"databyte\":\"welcome to china\",\"datafix32\":1,"
"\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802,"
"\"datafloat_scientific\":123456792,\"datadouble_scientific\":123456789}]}",
info1.data());
#endif
}
TEST_F(ProtobufJsonTest, pb_to_json_unicode_case) {
AddressBook address_book;
Person* person = address_book.add_person();
person->set_id(100);
char name[255*1024];
for (int j = 0; j < 1024; j++) {
for (int i = 0; i < 255; i++) {
name[j*255 + i] = i + 1;
}
}
name[255*1024 - 1] = '\0';
person->set_name(name);
person->set_data(-240000000);
person->set_data32(6);
person->set_data64(-1820000000);
person->set_datadouble(123.456);
person->set_datadouble_scientific(1.23456789e+08);
person->set_datafloat_scientific(1.23456789e+08);
person->set_datafloat(8.6123);
person->set_datau32(60);
person->set_datau64(960);
person->set_databool(0);
person->set_databyte("welcome to china");
person->set_datafix32(1);
person->set_datafix64(666);
person->set_datasfix32(120);
person->set_datasfix64(-802);
std::string info1;
std::string error;
google::protobuf::TextFormat::Printer printer;
std::string text;
printer.PrintToString(*person, &text);
printf("----------test pb to json------------\n\n");
bool ret = json2pb::ProtoMessageToJson(address_book, &info1, &error);
ASSERT_TRUE(ret);
base::IOBuf buf;
base::IOBufAsZeroCopyOutputStream stream(&buf);
bool res = json2pb::ProtoMessageToJson(address_book, &stream, NULL);
ASSERT_TRUE(res);
ASSERT_TRUE(!info1.compare(buf.to_string()));
}
TEST_F(ProtobufJsonTest, pb_to_json_edge_case) {
AddressBook address_book;
std::string info1;
std::string error;
bool ret = json2pb::ProtoMessageToJson(address_book, &info1, &error);
ASSERT_TRUE(ret);
info1.clear();
Person* person = address_book.add_person();
person->set_id(100);
person->set_name("baidu");
Person::PhoneNumber* phone_number = person->add_phone();
phone_number->set_number("1234556");
person->set_datadouble(-345.67);
person->set_datafloat(8.6123);
ret = json2pb::ProtoMessageToJson(address_book, &info1, &error);
ASSERT_TRUE(ret);
ASSERT_TRUE(error.empty());
std::string info3;
AddressBook data1;
std::string error1;
bool ret1 = json2pb::JsonToProtoMessage(info1, &data1, &error1);
ASSERT_TRUE(ret1);
ASSERT_TRUE(error1.empty());
std::string error2;
bool ret2 = json2pb::ProtoMessageToJson(data1, &info3, &error2);
ASSERT_TRUE(ret2);
ASSERT_TRUE(error2.empty());
}
TEST_F(ProtobufJsonTest, pb_to_json_expected_failed_case) {
AddressBook address_book;
std::string info1;
std::string error;
Person* person = address_book.add_person();
person->set_name("baidu");
person->set_email("welcome@baidu.com");
bool ret = json2pb::ProtoMessageToJson(address_book, &info1, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Missing required field: addressbook.Person.id", error.data());
address_book.clear_person();
person = address_book.add_person();
person->set_id(2);
person->set_email("welcome@baidu.com");
ret = json2pb::ProtoMessageToJson(address_book, &info1, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Missing required field: addressbook.Person.name", error.data());
address_book.clear_person();
person = address_book.add_person();
person->set_id(2);
person->set_name("name");
person->set_email("welcome@baidu.com");
ret = json2pb::ProtoMessageToJson(address_book, &info1, &error);
ASSERT_FALSE(ret);
ASSERT_STREQ("Missing required field: addressbook.Person.datadouble", error.data());
}
TEST_F(ProtobufJsonTest, pb_to_json_perf_case) {
AddressBook address_book;
Person* person = address_book.add_person();
person->set_id(100);
person->set_name("baidu");
person->set_email("welcome@baidu.com");
Person::PhoneNumber* phone_number = person->add_phone();
phone_number->set_number("number123");
phone_number->set_type(Person::HOME);
person->set_data(-240000000);
person->set_data32(6);
person->set_data64(-1820000000);
person->set_datadouble(123.456);
person->set_datadouble_scientific(1.23456789e+08);
person->set_datafloat_scientific(1.23456789e+08);
person->set_datafloat(8.6123);
person->set_datau32(60);
person->set_datau64(960);
person->set_databool(0);
person->set_databyte("welcome to china");
person->set_datafix32(1);
person->set_datafix64(666);
person->set_datasfix32(120);
person->set_datasfix64(-802);
std::string info1;
google::protobuf::TextFormat::Printer printer;
std::string text;
printer.PrintToString(*person, &text);
printf("text:%s\n", text.data());
printf("----------test pb to json performance------------\n\n");
ProfilerStart("pb_to_json_perf.prof");
base::Timer timer;
bool res;
float avg_time1 = 0;
float avg_time2 = 0;
const int times = 100000;
ASSERT_TRUE(json2pb::ProtoMessageToJson(address_book, &info1, NULL));
for (int i = 0; i < times; i++) {
std::string info3;
AddressBook data1;
timer.start();
res = json2pb::JsonToProtoMessage(info1, &data1, NULL);
timer.stop();
avg_time1 += timer.u_elapsed();
ASSERT_TRUE(res);
timer.start();
res = json2pb::ProtoMessageToJson(data1, &info3, NULL);
timer.stop();
avg_time2 += timer.u_elapsed();
ASSERT_TRUE(res);
}
avg_time1 /= times;
avg_time2 /= times;
ProfilerStop();
printf("avg time to convert json to pb is %fus\n", avg_time1);
printf("avg time to convert pb to json is %fus\n", avg_time2);
}
TEST_F(ProtobufJsonTest, pb_to_json_encode_decode_perf_case) {
JsonContextBodyEncDec json_data;
json_data.set_type(80000);
json_data.add_data_z058_array(200);
json_data.add_data_z058_array(300);
json_data.add_info("this is json data's info");
json_data.add_info("this is a test");
json_data.set_judge(true);
json_data.set_spur(3.45);
ContentEncDec * content = json_data.add__z064_content_test_z037__z064_();
content->set_uid_z042_("content info");
content->set_distance_info_(1234.56);
ExtEncDec* ext = content->mutable__ext_z037_t_();
ext->set_aa_ge_z040_(160000);
ext->set_databyte_z040_std_z058__z058_string_z041_("databyte");
ext->set_enum_z045__z045_type(ExtEncDec_PhoneTypeEncDec_WORK);
std::string info1;
google::protobuf::TextFormat::Printer printer;
std::string text;
printer.PrintToString(json_data, &text);
printf("text:%s\n", text.data());
ASSERT_TRUE(json2pb::ProtoMessageToJson(json_data, &info1, NULL));
printf("----------test pb to json encode decode performance------------\n\n");
ProfilerStart("pb_to_json_encode_decode_perf.prof");
base::Timer timer;
bool res;
float avg_time1 = 0;
float avg_time2 = 0;
const int times = 100000;
for (int i = 0; i < times; i++) {
std::string info3;
JsonContextBody json_body;
timer.start();
res = json2pb::JsonToProtoMessage(info1, &json_body, NULL);
timer.stop();
avg_time1 += timer.u_elapsed();
ASSERT_TRUE(res);
timer.start();
res = json2pb::ProtoMessageToJson(json_body, &info3, NULL);
timer.stop();
avg_time2 += timer.u_elapsed();
ASSERT_TRUE(res);
}
avg_time1 /= times;
avg_time2 /= times;
ProfilerStop();
printf("avg time to convert json to pb is %fus\n", avg_time1);
printf("avg time to convert pb to json is %fus\n", avg_time2);
}
TEST_F(ProtobufJsonTest, pb_to_json_complex_perf_case) {
std::ifstream in("jsonout", std::ios::in);
std::ostringstream tmp;
tmp << in.rdbuf();
std::string info3 = tmp.str();
in.close();
printf("----------test pb to json performance------------\n\n");
std::string error;
base::Timer timer;
bool res;
float avg_time1 = 0;
float avg_time2 = 0;
const int times = 10000;
gss::message::gss_us_res_t data;
json2pb::Json2PbOptions option;
option.base64_to_bytes = false;
timer.start();
res = JsonToProtoMessage(info3, &data, option, &error);
timer.stop();
avg_time1 += timer.u_elapsed();
ASSERT_TRUE(res);
ProfilerStart("pb_to_json_complex_perf.prof");
for (int i = 0; i < times; i++) {
std::string error1;
timer.start();
base::IOBuf buf;
base::IOBufAsZeroCopyOutputStream stream(&buf);
res = json2pb::ProtoMessageToJson(data, &stream, &error1);
timer.stop();
avg_time2 += timer.u_elapsed();
ASSERT_TRUE(res);
}
avg_time2 /= times;
ProfilerStop();
printf("avg time to convert pb to json is %fus\n", avg_time2);
}
TEST_F(ProtobufJsonTest, pb_to_json_to_string_complex_perf_case) {
std::ifstream in("jsonout", std::ios::in);
std::ostringstream tmp;
tmp << in.rdbuf();
std::string info3 = tmp.str();
in.close();
printf("----------test pb to json performance------------\n\n");
std::string error;
base::Timer timer;
bool res;
float avg_time1 = 0;
float avg_time2 = 0;
const int times = 10000;
gss::message::gss_us_res_t data;
json2pb::Json2PbOptions option;
option.base64_to_bytes = false;
timer.start();
res = JsonToProtoMessage(info3, &data, option, &error);
timer.stop();
avg_time1 += timer.u_elapsed();
ASSERT_TRUE(res);
ProfilerStart("pb_to_json_to_string_complex_perf.prof");
for (int i = 0; i < times; i++) {
std::string info4;
std::string error1;
timer.start();
std::string inf4;
res = json2pb::ProtoMessageToJson(data, &info4, &error1);
timer.stop();
avg_time2 += timer.u_elapsed();
ASSERT_TRUE(res);
}
avg_time2 /= times;
ProfilerStop();
printf("avg time to convert pb to json is %fus\n", avg_time2);
}
TEST_F(ProtobufJsonTest, encode_decode_case) {
std::string json_key = "abcdek123lske_slkejfl_l1kdle";
std::string field_name;
ASSERT_FALSE(json2pb::encode_name(json_key, field_name));
ASSERT_TRUE(field_name.empty());
std::string json_key_decode;
ASSERT_FALSE(json2pb::decode_name(field_name, json_key_decode));
ASSERT_TRUE(json_key_decode.empty());
json_key = "_Afledk2e*_+%leGi___hE_Z278_t#";
field_name.clear();
json2pb::encode_name(json_key, field_name);
const char* encode_json_key = "_Afledk2e_Z042___Z043__Z037_leGi___hE_Z278_t_Z035_";
ASSERT_TRUE(strcmp(field_name.data(), encode_json_key) == 0);
json_key_decode.clear();
json2pb::decode_name(field_name, json_key_decode);
ASSERT_TRUE(strcmp(json_key_decode.data(), json_key.data()) == 0);
json_key = "_ext%T_";
field_name.clear();
json2pb::encode_name(json_key, field_name);
encode_json_key = "_ext_Z037_T_";
ASSERT_TRUE(strcmp(field_name.data(), encode_json_key) == 0);
json_key_decode.clear();
json2pb::decode_name(field_name, json_key_decode);
ASSERT_TRUE(strcmp(json_key_decode.data(), json_key.data()) == 0);
std::string empty_key;
std::string empty_result;
ASSERT_FALSE(json2pb::encode_name(empty_key, empty_result));
ASSERT_TRUE(empty_result.empty() == true);
ASSERT_FALSE(json2pb::decode_name(empty_result, empty_key));
ASSERT_TRUE(empty_key.empty() == true);
}
TEST_F(ProtobufJsonTest, json_to_zero_copy_stream_normal_case) {
Person person;
person.set_name("hello");
person.set_id(9);
person.set_datadouble(2.2);
person.set_datafloat(1);
base::IOBuf iobuf;
base::IOBufAsZeroCopyOutputStream wrapper(&iobuf);
std::string error;
ASSERT_TRUE(json2pb::ProtoMessageToJson(person, &wrapper, &error)) << error;
std::string out = iobuf.to_string();
ASSERT_EQ("{\"name\":\"hello\",\"id\":9,\"datadouble\":2.2,\"datafloat\":1.0}", out);
}
TEST_F(ProtobufJsonTest, zero_copy_stream_to_json_normal_case) {
base::IOBuf iobuf;
iobuf = "{\"name\":\"hello\",\"id\":9,\"datadouble\":2.2,\"datafloat\":1.0}";
base::IOBufAsZeroCopyInputStream wrapper(iobuf);
Person person;
ASSERT_TRUE(json2pb::JsonToProtoMessage(&wrapper, &person));
ASSERT_STREQ("hello", person.name().c_str());
ASSERT_EQ(9, person.id());
ASSERT_EQ(2.2, person.datadouble());
ASSERT_EQ(1, person.datafloat());
}
TEST_F(ProtobufJsonTest, extension_case) {
std::string json = "{\"name\":\"hello\",\"id\":9,\"datadouble\":2.2,\"datafloat\":1.0,\"hobby\":\"coding\"}";
Person person;
ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &person));
ASSERT_STREQ("coding", person.GetExtension(addressbook::hobby).data());
std::string output;
ASSERT_TRUE(json2pb::ProtoMessageToJson(person, &output));
ASSERT_EQ("{\"hobby\":\"coding\",\"name\":\"hello\",\"id\":9,\"datadouble\":2.2,\"datafloat\":1.0}", output);
}
}
// Copyright (c) 2015 Baidu.com, Inc. All Rights Reserved
// Author: Zhangyi Chen (chenzhangyi01@baidu.com)
// Date: 2015/10/10 17:55:13
#include "repeated.pb.h"
#include <gtest/gtest.h>
#include <json2pb/pb_to_json.h>
class RepeatedFieldTest : public testing::Test {
protected:
void SetUp() {}
void TearDown() {}
};
TEST_F(RepeatedFieldTest, empty_array) {
RepeatedMessage m;
std::string json;
ASSERT_TRUE(json2pb::ProtoMessageToJson(m, &json));
std::cout << json << std::endl;
m.add_strings();
m.add_ints(1);
m.add_msgs();
json.clear();
ASSERT_TRUE(json2pb::ProtoMessageToJson(m, &json));
std::cout << json << std::endl;
}
{"ResultCode":0,"QueryID":1234567111,"Result":[{"ResultURL":"demo_mola_service","Weight":0,"TimingNeed":0,"DisplayData":"EAC5dAAADAAAABQHU3RkU3RnACRSAAAUB1N0ZFN0bAAIAAAA0A0LX3VwZGF0ZV90aW1lADE0MzYzNzQ3MzUA0AQ+bG9jAGh0dHA6Ly9vcGVuLmJhaWR1LmNvbS9xP3I9MjEwMjgmaz0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUA0AQHa2V5AMH1tcK7qgDQBEJ1cmwAaHR0cDovL3d3dy5iYWlkdS5jb20vcz93ZD0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmc3JjaWQ9MjEwMjgAIAWEAAAAbGlzdAAgAAAA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQAUD2xpc3QjbnVtI2JhaWR1ACAAAABQBS8IAABkcnN2AGNhcmRzX2luZm97ZX1leUl4TkRoallqWXhOakl3TldNME56Y3lOelEzTW1Vek5XUXlabU0zT1RoaE15STZXelFzZXlKallqWmpaV0kyWkRVNFpERTBNVGcxWWpBd1lXSmlPRGM0WkdSa1lUVTRPU0k2V3lKY2RUa3daV1JjZFRWaVkyTmNkVFUzWTJVaUxDSmNkVFUzTkRkY2RUUmxNMkZjZFRrNU9UbGNkVFpsTW1aY2RUVTJaR0pjZFRVNU1qZGNkVFU1TWpsY2RUY3pPR0lpWFN3aVpqZzNOV05pT0dSaVlUWTNOR0kyTjJKaU5XWXpOakJqWlRkbU5XTmhPRFFpT2xzaVhIVTVOalE0WEhVM1pqaGxYSFUzTkRKaElpd2lYSFUzTmpka1hIVTFZVEU0WEhVMVlqVXdYSFUwWlRKa1hIVTBabU5tWEhVMFpUTmtYSFUzTmpnMFhIVTFZekJtWEhVNU56VXlJbDBzSWpBMU5qQXpNbVJsWlRJd05EUm1OVGRpTlRJd056azJNek5rWXpGalkyUTVJanBiSWx4MU56TTRZbHgxTnprMU5seDFPR1F5TkNJc0lseDFOMlF5TUZ4MU9UZzVZMXgxTm1Vd05WeDFOMlZoWmx4MU5UazNNMXgxTnprMVpWeDFOR1V3WkZ4MU9EQXdNVngxTkdZeU1GeDFOVGswTnlKZExDSXlZalpoTm1aaFpqQmtNRGMwTldaaFlUQXlaRE5rT0RWaU5UVTFOakExT0NJNld5SmNkVFV6WlRSY2RUVTVNamxjZFRSbE5UQWlMQ0l5TURFMVhIVTFaVGMwWEhVNU9UazVYSFUyWlRKbVhIVTNOVE0xWEhVMVpqY3hYSFU0TWpneVhIVTFPVEkzWEhVMFpqZG1JbDE5TENKY2RUazVPVGxjZFRabE1tWmNkVFkyTUdWY2RUWTJNV1lpTERGZExDSTRZalF3WkRsaU1ETTFNR1ptTmpnelkyWTFPR05pWkRRM1ltUTFOR0V5TlNJNld6Z3NleUpqWXpJMVpqaGhZVFU1TnpjME5qZGlZakpsTTJJMFpqVm1PVGxtWlROaU55STZXeUpjZFRnek1ETmNkVFJsTVdWY2RUUmxNV1VpTENKY2RUZ3pNRE5jZFRVeFlqQmNkVFV4WWpCY2RUVm1NV1pjZFRWbU1XWmNkVGc0WVdKY2RUYzFPVEZjZFRjNVl6RmNkVGMxTVdaY2RUVmlOVEFpWFN3aU5UVmhNRFUxWWpJMVlURm1ORGt5WTJKaVlURXhNakEyTlRRMVlUa3dOakFpT2xzaVhIVTFaamt3WEhVMVlUQTNJaXdpWEhVMk5qRm1YSFUzTWpNM1hIVTFaVGN5WEhVMU9UY3pYSFUxTVRObVhIVTFPVGN6WEhVMU9USTNYSFUxTXpReFhIVTFNVFppWEhVMU0yUTRJbDBzSW1GbE5UZGtNVGd3WW1aak9EUTVabUZpWW1VNU9UWTBOekJpWm1Vek5XTTJJanBiSWx4MU5XWXlNRngxTlRNMllseDFOVEEyTlNJc0lseDFOakl4TVZ4MU5qWXlabHgxTm1ZeE5GeDFPR0ptTkZ4MU5XSmlObHgxTkdVeVpGeDFOakpqTlZ4MU5HVm1ZbHgxTldKbVkxeDFOV1V3T0NKZExDSTJNRFUzTURZM1pXVTBOamcwTjJRd1lqUmxOR1l6WkdabU1HSmtPVFJpTmlJNld5SmNkVFUwTmpoY2RUWTJNV1pjZFRsaE56QmNkVFZsTnpRaUxDSXhPVGt5WEhVMVpUYzBYSFUyTmpGbVhIVTNNak0zWEhVMFpqVmpYSFUxTkdNeFhIVTNNakEyWEhVMU0yUXhYSFUxWlRjMElsMHNJbUUxWWpaaFlUSXhaakF3TXpRNU9UUTRNMlE1TkdJMU1ERTVNVEEzWlRVMklqcGJJbHgxTmpjek1WeDFOR1V6WkZ4MU5UQXlPU0lzSWpFeVhIVTFaVGMwWEhVMFpUTmhYSFUxTWpFNFhIVTFabUkzWEhVMU16UmxYSFUwWldFM1hIVTBaVEJpWEhVMFpUQXdYSFUxT1RjeklsMHNJbVUzWmpFMFpUVmtNelV3TXpSalptTmhOamRqTTJRNE5HUXdZV05qT1RrMUlqcGJJbHgxTldNM01WeDFOVE5sTTF4MU56WTNaVngxTmpCbE1DSXNJbHgxTlRFMk9GeDFObU14TVZ4MU5UazNNMXgxTnprMVpWeDFOV1JtTWx4MU5UTmtPRngxTmpJeE1GeDFPREJoTlZ4MU5XVXdPRngxTlRrM05pSmRMQ0l3WVRSaE1qQXlZalZtT1dZME5XUTJPR1ZrWkRRMU0yTXpNbUkzTkRFMVpDSTZXeUpjZFRSbU5UVmNkVFkxT0RkY2RUaG1PRGtpTENKY2RUVmpNVEZjZFRZM09UZGNkVGhrWWpOY2RUYzBNRE5jZFRSbE1EQmNkVGN3WVdWY2RUZ3dNR05jZFRkbFlUSWlYU3dpTkdFNVlUZzJPVFl3Tmpnd05EQm1Zemt6T0RNeFpEUmlPRGt4WXpObFlqRWlPbHNpWEhVNU1Ea3pYSFU0WkRnMUlpd2lYSFUwWlRKa1hIVTFObVprWEhVNE5EVTNYSFUxTkRCa1hIVTBaVEF3WEhVM1pXSm1YSFUxWmpjeFhIVTJOakZtSWwxOUxDSmNkVGMyWmpoY2RUVXhOek5jZFRSbFltRmNkVGN5TmpraUxERmRmUT09e3N9c2hvd19yZWFzb257ZX0xe3N9dGl0bGVfdHlwZXtlfTJfNgAQEAtMAABSaWdodF9SZXNvdXJjZXMABAAAANAEQnVybABodHRwOi8vd3d3LmJhaWR1LmNvbS9zP3dkPSVFNSU4OCU5OCVFNSVCRSVCNyVFNSU4RCU4RSZzcmNpZD0yMTAyOAAgBZFLAABjYXJkAAIAAAAQAOYlAAAMAAAAIAWqBgAAdW5pdAAQAAAAEABkAAAABAAAANAFB25hbWUA1uzA9tm7ANAEIXVyaQBhNWI2YWEyMWYwMDM0OTk0ODNkOTRiNTAxOTEwN2U1NgDQBQhwYXRoAGxpc3RbMF0A0AkNdXJpX2Ryc3YAc2NvcmU9MC40OTQ3ABAAZAAAAAQAAADQBQduYW1lALe22KnYqQDQBCF1cmkAY2MyNWY4YWE1OTc3NDY3YmIyZTNiNGY1Zjk5ZmUzYjcA0AUIcGF0aABsaXN0WzFdANAJDXVyaV9kcnN2AHNjb3JlPTAuMzkzNwAQAGYAAAAEAAAA0AUJbmFtZQDJvb/asNm73QDQBCF1cmkAZTdmMTRlNWQzNTAzNGNmY2E2N2MzZDg0ZDBhY2M5OTUA0AUIcGF0aABsaXN0WzJdANAJDXVyaV9kcnN2AHNjb3JlPTAuMzA2MQAQAGIAAAAEAAAA0AUFbmFtZQDQ7L2/ANAEIXVyaQA1NWEwNTViMjVhMWY0OTJjYmJhMTEyMDY1NDVhOTA2MADQBQhwYXRoAGxpc3RbM10A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yOTk4ABAAZgAAAAQAAADQBQluYW1lANbc0Mez28TqANAEIXVyaQA2MDU3MDY3ZWU0Njg0N2QwYjRlNGYzZGZmMGJkOTRiNgDQBQhwYXRoAGxpc3RbNF0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yOTkyABAAYgAAAAQAAADQBQVuYW1lALXLs6wA0AQhdXJpADRhOWE4Njk2MDY4MDQwZmM5MzgzMWQ0Yjg5MWMzZWIxANAFCHBhdGgAbGlzdFs1XQDQCQ11cmlfZHJzdgBzY29yZT0wLjI5NTUAEABkAAAABAAAANAFB25hbWUAus7OxLvUANAEIXVyaQAwYTRhMjAyYjVmOWY0NWQ2OGVkZDQ1M2MzMmI3NDE1ZADQBQhwYXRoAGxpc3RbNl0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yOTMwABAAZAAAAAQAAADQBQduYW1lANXFzsC9oQDQBCF1cmkAYWU1N2QxODBiZmM4NDlmYWJiZTk5NjQ3MGJmZTM1YzYA0AUIcGF0aABsaXN0WzddANAJDXVyaV9kcnN2AHNjb3JlPTAuMjg5OAAQAGQAAAAEAAAA0AUHbmFtZQDV1LG+y64A0AQhdXJpADM5Y2RlNzhiNjFmMzQ2YjU5MzE0NWNkMWQxNmIyMWVmANAFCHBhdGgAbGlzdFs4XQDQCQ11cmlfZHJzdgBzY29yZT0wLjI4OTcAEABkAAAABAAAANAFB25hbWUA1cW80rvUANAEIXVyaQA0MjEwZWNlZjg1MzI0ODMxOTIyZjRkYzUzZDBhZTBmYwDQBQhwYXRoAGxpc3RbOV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yODc2ABAAZQAAAAQAAADQBQduYW1lAMy307336wDQBCF1cmkAOWVhOTgxMWNkMTNlNDAwZmI2Mjc0OTA3YzRhYmU0NzkA0AUJcGF0aABsaXN0WzEwXQDQCQ11cmlfZHJzdgBzY29yZT0wLjI4NjcAEABlAAAABAAAANAFB25hbWUA1cW+++W4ANAEIXVyaQAxOTFkOWNhOWJmYjY0NjliOGNjMmQ4NmY4MjY4MTM5YwDQBQlwYXRoAGxpc3RbMTFdANAJDXVyaV9kcnN2AHNjb3JlPTAuMjgzNgAQAGcAAAAEAAAA0AUJbmFtZQDLxNChzOzN9QDQBCF1cmkAMTk5MjU2ZTdiZTlkNGFjZThlYzcyMTI1OTdkMzA3ODEA0AUJcGF0aABsaXN0WzEyXQDQCQ11cmlfZHJzdgBzY29yZT0wLjI4MTIAEABlAAAABAAAANAFB25hbWUAu8bKpdLAANAEIXVyaQBjZmZhZWVjNmY0MDY0OTUyYWZlMzEwMzdlNzkwM2U0MADQBQlwYXRoAGxpc3RbMTNdANAJDXVyaV9kcnN2AHNjb3JlPTAuMjc3OAAQAGUAAAAEAAAA0AUHbmFtZQCy1L6u08UA0AQhdXJpAGMwM2NjYjY5YjQ4MDRjOWViMzM5ZmIyODY4NmMwNzBmANAFCXBhdGgAbGlzdFsxNF0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yNzc0ABAAYwAAAAQAAADQBQVuYW1lANXFw/QA0AQhdXJpAGRkNmU2YjI3ZjYzNDQ2OTE5NGE1N2UwMDFjNWQ5NmYyANAFCXBhdGgAbGlzdFsxNV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yNzczABQPdW5pdCNudW0jYmFpZHUAEAAAANAJBmNhcmR0eXBlAHJlY29tANAHIWNhcmRpZAA4YjQwZDliMDM1MGZmNjgzY2Y1OGNiZDQ3YmQ1NGEyNQDQCQlzdWJ0aXRsZQDP4LnYyMvO7wDQBEJ1cmwAaHR0cDovL3d3dy5iYWlkdS5jb20vcz93ZD0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmc3JjaWQ9MjEwMjgA0AgCc2hvd3JvdwAyANAJAnNob3dudW1zADgAIAX6HQAAbGlzdAAQAAAAEADdAQAACwAAANAFB25hbWUA1uzA9tm7ANAENmltZwBodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTM3NDgzOTg5NjAsMTc5ODE3MTgzMCZmbT01OADQB11wYXJhbXMAd2Q9JUU2JTlDJUIxJUU0JUI4JUJEJUU1JTgwJUE5JnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMjgA0AQHdGlwANbswPbZuwDQBRVhdHRyADEyxOrOqsH1tcK7qrL6z8LSu8WuANAJBGF0dHJ0eXBlAFJFTADQCDVhdHRycGljAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9NTE4MzU2MDQ1LDM1NDUwMzg4ODUmZm09NTgA0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQBhNWI2YWEyMWYwMDM0OTk0ODNkOTRiNTAxOTEwN2U1NgDQBzZhdHRyaWQAYTViNmFhMjFmMDAzNDk5NDgzZDk0YjUwMTkxMDdlNTYgMTLE6s6qwfW1wruqsvrPwtK7xa4A0AYnaW1naWQAYTViNmFhMjFmMDAzNDk5NDgzZDk0YjUwMTkxMDdlNTZfNzVfNzUAEADeAQAACwAAANAFB25hbWUAt7bYqdipANAENmltZwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTI2NjczMTgxMzEsMzExMzAzNTg3MSZmbT01OADQB11wYXJhbXMAd2Q9JUU4JThDJTgzJUU0JUI4JTlFJUU0JUI4JTlFJnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMjgA0AQHdGlwALe22KnYqQDQBRVhdHRyALe2sfmx+bXctdyxu9LJy73J+tfTANAJBGF0dHJ0eXBlAFRBRwDQCDZhdHRycGljAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9Mzc5NTMwNDk1NCwxNDEyMDc0MTgyJmZtPTU4ANAOAmF0dHJwaWNpc2xpbmsAMADQBCF1cmkAY2MyNWY4YWE1OTc3NDY3YmIyZTNiNGY1Zjk5ZmUzYjcA0Ac2YXR0cmlkAGNjMjVmOGFhNTk3NzQ2N2JiMmUzYjRmNWY5OWZlM2I3ILe2sfmx+bXctdyxu9LJy73J+tfTANAGJ2ltZ2lkAGNjMjVmOGFhNTk3NzQ2N2JiMmUzYjRmNWY5OWZlM2I3Xzc1Xzc1ABAA6AEAAAsAAADQBQluYW1lAMm9v9qw2bvdANAENWltZwBodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTMwMDQ3NzkwMTMsODA4OTY4OTkwJmZtPTU4ANAHZnBhcmFtcwB3ZD0lRTUlQjElQjElRTUlOEYlQTMlRTclOTklQkUlRTYlODMlQTAmcnN2X2NxPSVFNSU4OCU5OCVFNSVCRSVCNyVFNSU4RCU4RSZyc3ZfZGw9MF9yaWdodF9yZWNvbV8yMTAyOADQBAl0aXAAyb2/2rDZu90A0AUVYXR0cgDIq8Pxxa7J8dLRseSzybfKyqbEzADQCQRhdHRydHlwZQBUQUcA0Ag0YXR0cnBpYwBodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTExNDk0MDM5Myw1NTQxNDQ0MTkmZm09NTgA0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQBlN2YxNGU1ZDM1MDM0Y2ZjYTY3YzNkODRkMGFjYzk5NQDQBzZhdHRyaWQAZTdmMTRlNWQzNTAzNGNmY2E2N2MzZDg0ZDBhY2M5OTUgyKvD8cWuyfHS0bHks8m3ysqmxMwA0AYnaW1naWQAZTdmMTRlNWQzNTAzNGNmY2E2N2MzZDg0ZDBhY2M5OTVfNzVfNzUAEADRAQAACwAAANAFBW5hbWUA0Oy9vwDQBDZpbWcAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0xODQxNTQ2OTU3LDQxOTA0MTQyNjEmZm09NTgA0AdUcGFyYW1zAHdkPSVFNSVCRSU5MCVFNSVBOCU4NyZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDI4ANAEBXRpcADQ7L2/ANAFFWF0dHIA0MfSr7jJxa62+cWutPPKrrDLseQA0AkEYXR0cnR5cGUAVEFHANAINmF0dHJwaWMAaHR0cDovL3QxMS5iYWlkdS5jb20vaXQvdT0xMTU1Mzg2NDYxLDQyMDc4MjA2NzgmZm09NTgA0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQA1NWEwNTViMjVhMWY0OTJjYmJhMTEyMDY1NDVhOTA2MADQBzZhdHRyaWQANTVhMDU1YjI1YTFmNDkyY2JiYTExMjA2NTQ1YTkwNjAg0MfSr7jJxa62+cWutPPKrrDLseQA0AYnaW1naWQANTVhMDU1YjI1YTFmNDkyY2JiYTExMjA2NTQ1YTkwNjBfNzVfNzUAEADoAQAACwAAANAFCW5hbWUA1tzQx7PbxOoA0AQ1aW1nAGh0dHA6Ly90MTIuYmFpZHUuY29tL2l0L3U9MjMwMzQyODA3OSw5ODM3MTQ2MjQmZm09NTgA0AdmcGFyYW1zAHdkPSVFNSU5MSVBOCVFNiU5OCU5RiVFOSVBOSVCMCVFNSVCOSVCNCZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDI4ANAECXRpcADW3NDHs9vE6gDQBRVhdHRyADE5OTLE6tDH0q/X98a3say3osTqANAJBGF0dHJ0eXBlAFRBRwDQCDRhdHRycGljAGh0dHA6Ly90MTAuYmFpZHUuY29tL2l0L3U9NDE2ODk3OTQsMjYyMTAzMTQ1MCZmbT01OADQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpADYwNTcwNjdlZTQ2ODQ3ZDBiNGU0ZjNkZmYwYmQ5NGI2ANAHNmF0dHJpZAA2MDU3MDY3ZWU0Njg0N2QwYjRlNGYzZGZmMGJkOTRiNiAxOTkyxOrQx9Kv1/fGt7Gst6LE6gDQBidpbWdpZAA2MDU3MDY3ZWU0Njg0N2QwYjRlNGYzZGZmMGJkOTRiNl83NV83NQAQAMkBAAALAAAA0AUFbmFtZQC1y7OsANAENmltZwBodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTE2NDIwMzExNzksMzY1MTgzMDU1NiZmbT01OADQB1RwYXJhbXMAd2Q9JUU5JTgyJTkzJUU4JUI2JTg1JnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMjgA0AQFdGlwALXLs6wA0AURYXR0cgDW0Ln61vjD+9K7z9/TsNDHANAJBGF0dHJ0eXBlAFRBRwDQCDZhdHRycGljAGh0dHA6Ly90MTAuYmFpZHUuY29tL2l0L3U9MTMwMzY2NzI3NCwxNTM1MzA3NTU5JmZtPTU4ANAOAmF0dHJwaWNpc2xpbmsAMADQBCF1cmkANGE5YTg2OTYwNjgwNDBmYzkzODMxZDRiODkxYzNlYjEA0AcyYXR0cmlkADRhOWE4Njk2MDY4MDQwZmM5MzgzMWQ0Yjg5MWMzZWIxINbQufrW+MP70rvP39Ow0McA0AYnaW1naWQANGE5YTg2OTYwNjgwNDBmYzkzODMxZDRiODkxYzNlYjFfNzVfNzUAEADWAQAACwAAANAFB25hbWUAus7OxLvUANAENmltZwBodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTI5NTIwMzU3MTMsMjgwNDczOTU1MiZmbT01OADQB11wYXJhbXMAd2Q9JUU0JUJEJTk1JUU2JTk2JTg3JUU4JUJFJTg5JnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMjgA0AQHdGlwALrOzsS71ADQBRFhdHRyAMnZwdbX48fy0rvF2rb4uuwA0AkEYXR0cnR5cGUAVEFHANAINmF0dHJwaWMAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0xOTk5NjI2OTgzLDEyNzk3MTI3NTYmZm09NTgA0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQAwYTRhMjAyYjVmOWY0NWQ2OGVkZDQ1M2MzMmI3NDE1ZADQBzJhdHRyaWQAMGE0YTIwMmI1ZjlmNDVkNjhlZGQ0NTNjMzJiNzQxNWQgydnB1tfjx/LSu8Xatvi67ADQBidpbWdpZAAwYTRhMjAyYjVmOWY0NWQ2OGVkZDQ1M2MzMmI3NDE1ZF83NV83NQAQANwBAAALAAAA0AUHbmFtZQDVxc7AvaEA0AQ1aW1nAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9ODYyMzM2MDUxLDIzODQ5NDE1OTMmZm09NTgA0AddcGFyYW1zAHdkPSVFNSVCQyVBMCVFNSU4RCVBQiVFNSU4MSVBNSZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDI4ANAEB3RpcADVxc7AvaEA0AUVYXR0cgDO0srH0d3LtbzS1tC1o8jOtbzKpgDQCQRhdHRydHlwZQBUQUcA0Ag1YXR0cnBpYwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTE4NDU2NTk0MiwxODMwNjcyNTgwJmZtPTU4ANAOAmF0dHJwaWNpc2xpbmsAMADQBCF1cmkAYWU1N2QxODBiZmM4NDlmYWJiZTk5NjQ3MGJmZTM1YzYA0Ac2YXR0cmlkAGFlNTdkMTgwYmZjODQ5ZmFiYmU5OTY0NzBiZmUzNWM2IM7SysfR3cu1vNLW0LWjyM61vMqmANAGJ2ltZ2lkAGFlNTdkMTgwYmZjODQ5ZmFiYmU5OTY0NzBiZmUzNWM2Xzc1Xzc1ABAA2QEAAAsAAADQBQduYW1lANXUsb7LrgDQBDVpbWcAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT01NTU4NDgzNzUsMzQ1MDg1MTg2OCZmbT01OADQB11wYXJhbXMAd2Q9JUU4JUI1JUI1JUU2JTlDJUFDJUU2JUIwJUI0JnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMjgA0AQHdGlwANXUsb7LrgDQBRNhdHRyANOyxvi5pr/avLzA1sb30d3UsQDQCQRhdHRydHlwZQBUQUcA0Ag2YXR0cnBpYwBodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTMyNDkzNzI0MjcsMjM1Nzg5NDc3NyZmbT01OADQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpADM5Y2RlNzhiNjFmMzQ2YjU5MzE0NWNkMWQxNmIyMWVmANAHNGF0dHJpZAAzOWNkZTc4YjYxZjM0NmI1OTMxNDVjZDFkMTZiMjFlZiDTssb4uaa/2ry8wNbG99Hd1LEA0AYnaW1naWQAMzljZGU3OGI2MWYzNDZiNTkzMTQ1Y2QxZDE2YjIxZWZfNzVfNzUAEADbAQAACwAAANAFB25hbWUA1cW80rvUANAENWltZwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTkwMzg3Nzc0OCwxNTA2MTI3NzAzJmZtPTU4ANAHXXBhcmFtcwB3ZD0lRTUlQkMlQTAlRTUlQUUlQjYlRTglQkUlODkmcnN2X2NxPSVFNSU4OCU5OCVFNSVCRSVCNyVFNSU4RCU4RSZyc3ZfZGw9MF9yaWdodF9yZWNvbV8yMTAyOADQBAd0aXAA1cW80rvUANAFFGF0dHIA0+u3orjns/bR3bDEw8W359TGMgDQCQRhdHRydHlwZQBUQUcA0Ag2YXR0cnBpYwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTEyNDcxNDAxMzksMjE1Njc2Njg2NSZmbT01OADQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpADQyMTBlY2VmODUzMjQ4MzE5MjJmNGRjNTNkMGFlMGZjANAHNWF0dHJpZAA0MjEwZWNlZjg1MzI0ODMxOTIyZjRkYzUzZDBhZTBmYyDT67eiuOez9tHdsMTDxbfn1MYyANAGJ2ltZ2lkADQyMTBlY2VmODUzMjQ4MzE5MjJmNGRjNTNkMGFlMGZjXzc1Xzc1ABAA2QEAAAsAAADQBQduYW1lAMy307336wDQBDZpbWcAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0yMDg1NjQ1Nzk0LDIwNjcxOTUzOTEmZm09NTgA0AddcGFyYW1zAHdkPSVFOCVCMCVBRCVFNSU5MiU4RiVFOSVCQSU5RiZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDI4ANAEB3RpcADMt9O99+sA0AUTYXR0cgDP47jb0d3S1cjL0K274bvhs6QA0AkEYXR0cnR5cGUAVEFHANAINWF0dHJwaWMAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0yNjI2MzM3NzY2LDgxMTAyOTQ4MCZmbT01OADQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpADllYTk4MTFjZDEzZTQwMGZiNjI3NDkwN2M0YWJlNDc5ANAHNGF0dHJpZAA5ZWE5ODExY2QxM2U0MDBmYjYyNzQ5MDdjNGFiZTQ3OSDP47jb0d3S1cjL0K274bvhs6QA0AYnaW1naWQAOWVhOTgxMWNkMTNlNDAwZmI2Mjc0OTA3YzRhYmU0NzlfNzVfNzUAEADVAQAACwAAANAFB25hbWUA1cW+++W4ANAENmltZwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTIzMTc0ODY2MjUsMTQzNDM4MjA0MyZmbT01OADQB11wYXJhbXMAd2Q9JUU1JUJDJUEwJUU5JTkyJUE3JUU3JTk0JUFGJnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMjgA0AQHdGlwANXFvvvluADQBRFhdHRyAMyozeW12tK7xvjWysPAxa4A0AkEYXR0cnR5cGUAVEFHANAINWF0dHJwaWMAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0xMzgwODQ2MjE4LDQ5ODk3Mjk0NyZmbT01OADQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpADE5MWQ5Y2E5YmZiNjQ2OWI4Y2MyZDg2ZjgyNjgxMzljANAHMmF0dHJpZAAxOTFkOWNhOWJmYjY0NjliOGNjMmQ4NmY4MjY4MTM5YyDMqM3ltdrSu8b41srDwMWuANAGJ2ltZ2lkADE5MWQ5Y2E5YmZiNjQ2OWI4Y2MyZDg2ZjgyNjgxMzljXzc1Xzc1ABAA4wEAAAsAAADQBQluYW1lAMvE0KHM7M31ANAENmltZwBodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTEwMTMxMDYyNjIsMzY2NDY0Mjk4MCZmbT01OADQB2ZwYXJhbXMAd2Q9JUU1JTlCJTlCJUU1JUIwJThGJUU1JUE0JUE5JUU3JThFJThCJnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMjgA0AQJdGlwAMvE0KHM7M31ANAFEWF0dHIA0+nA1sim1+7J8bXEyfG7sADQCQRhdHRydHlwZQBUQUcA0Ag2YXR0cnBpYwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTI1NzI4NDAxOTYsNDAzMTI5NDY2NSZmbT01OADQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpADE5OTI1NmU3YmU5ZDRhY2U4ZWM3MjEyNTk3ZDMwNzgxANAHMmF0dHJpZAAxOTkyNTZlN2JlOWQ0YWNlOGVjNzIxMjU5N2QzMDc4MSDT6cDWyKbX7snxtcTJ8buwANAGJ2ltZ2lkADE5OTI1NmU3YmU5ZDRhY2U4ZWM3MjEyNTk3ZDMwNzgxXzc1Xzc1ABAA2gEAAAsAAADQBQduYW1lALvGyqXSwADQBDZpbWcAaHR0cDovL3QxMS5iYWlkdS5jb20vaXQvdT0yNDkxNzYxNTgwLDIxMjU2Njk1ODYmZm09NTgA0AddcGFyYW1zAHdkPSVFOSVCQiU4NCVFNSU5QyVBMyVFNCVCRSU5RCZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDI4ANAEB3RpcAC7xsql0sAA0AUTYXR0cgDTsMrTuOjJzLbgxtzFrtLVyMsA0AkEYXR0cnR5cGUAVEFHANAINmF0dHJwaWMAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0xNTc2ODgzNDMzLDIyMzU2MzQ1MzEmZm09NTgA0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQBjZmZhZWVjNmY0MDY0OTUyYWZlMzEwMzdlNzkwM2U0MADQBzRhdHRyaWQAY2ZmYWVlYzZmNDA2NDk1MmFmZTMxMDM3ZTc5MDNlNDAg07DK07joycy24Mbcxa7S1cjLANAGJ2ltZ2lkAGNmZmFlZWM2ZjQwNjQ5NTJhZmUzMTAzN2U3OTAzZTQwXzc1Xzc1ABAA0gEAAAsAAADQBQduYW1lALLUvq7TxQDQBDZpbWcAaHR0cDovL3QxMS5iYWlkdS5jb20vaXQvdT0zNzUyMjIwNDUxLDQyNTg1NzM5NTUmZm09NTgA0AddcGFyYW1zAHdkPSVFOCU4QiU4RCVFNCVCQSU5NSVFNCVCQyU5OCZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDI4ANAEB3RpcACy1L6u08UA0AUPYXR0cgCxyLOk1PPRxcPA0NS40ADQCQRhdHRydHlwZQBUQUcA0Ag2YXR0cnBpYwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTM5MTc4Mjg2MDYsNDA0MjI3MDI4OCZmbT01OADQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpAGMwM2NjYjY5YjQ4MDRjOWViMzM5ZmIyODY4NmMwNzBmANAHMGF0dHJpZABjMDNjY2I2OWI0ODA0YzllYjMzOWZiMjg2ODZjMDcwZiCxyLOk1PPRxcPA0NS40ADQBidpbWdpZABjMDNjY2I2OWI0ODA0YzllYjMzOWZiMjg2ODZjMDcwZl83NV83NQAQAM4BAAALAAAA0AUFbmFtZQDVxcP0ANAENGltZwBodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTE3NTAxMTMxMiwxNjI4NjYwMTMmZm09NTgA0AdUcGFyYW1zAHdkPSVFNSVCQyVBMCVFNiU5NSU4RiZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDI4ANAEBXRpcADVxcP0ANAFFWF0dHIA0ru0+sTQ07DD1LXEw87W0MfpyMsA0AkEYXR0cnR5cGUAVEFHANAINWF0dHJwaWMAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0xNTgzNjE3NTYzLDI5MzM3ODg0MyZmbT01OADQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpAGRkNmU2YjI3ZjYzNDQ2OTE5NGE1N2UwMDFjNWQ5NmYyANAHNmF0dHJpZABkZDZlNmIyN2Y2MzQ0NjkxOTRhNTdlMDAxYzVkOTZmMiDSu7T6xNDTsMPUtcTDztbQx+nIywDQBidpbWdpZABkZDZlNmIyN2Y2MzQ0NjkxOTRhNTdlMDAxYzVkOTZmMl83NV83NQAUD2xpc3QjbnVtI2JhaWR1ABAAAAAgDRgAAAB0b3BfY2FyZF9wcm0AAQAAABAADgAAAAEAAADQBQJzaG93ADEAFBd0b3BfY2FyZF9wcm0jbnVtI2JhaWR1AAEAAAAQAJslAAAMAAAAIAWmBgAAdW5pdAAQAAAAEABkAAAABAAAANAFB25hbWUAucXM7MDWANAEIXVyaQAyYjZhNmZhZjBkMDc0NWZhYTAyZDNkODViNTU1NjA1OADQBQhwYXRoAGxpc3RbMF0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yOTUzABAAZAAAAAQAAADQBQduYW1lAM311+bPzQDQBCF1cmkAMDU2MDMyZGVlMjA0NGY1N2I1MjA3OTYzM2RjMWNjZDkA0AUIcGF0aABsaXN0WzFdANAJDXVyaV9kcnN2AHNjb3JlPTAuMjk1MQAQAGQAAAAEAAAA0AUHbmFtZQC5+bi7s8cA0AQhdXJpAGNiNmNlYjZkNThkMTQxODViMDBhYmI4NzhkZGRhNTg5ANAFCHBhdGgAbGlzdFsyXQDQCQ11cmlfZHJzdgBzY29yZT0wLjI5MTcAEABkAAAABAAAANAFB25hbWUAs8LDwOf3ANAEIXVyaQBmODc1Y2I4ZGJhNjc0YjY3YmI1ZjM2MGNlN2Y1Y2E4NADQBQhwYXRoAGxpc3RbM10A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yOTE0ABAAYgAAAAQAAADQBQVuYW1lANbs0vAA0AQhdXJpADQ4NjRkZjY1ODY3YjRhNTA5ZTc3YzljNjUxODU2NDk4ANAFCHBhdGgAbGlzdFs0XQDQCQ11cmlfZHJzdgBzY29yZT0wLjI1OTMAEABkAAAABAAAANAFB25hbWUAwbq80rvUANAEIXVyaQBmM2Y5MmQ4ZjYzMTk0NDhhYTI2YzA4ZmJmZGJiNDhjNQDQBQhwYXRoAGxpc3RbNV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yNTEzABAAZAAAAAQAAADQBQduYW1lANbcyPO3ogDQBCF1cmkAZjIyN2ZiZDFiNDExNDJiZGE3ZWY5YmQzYTMyZmZkYzQA0AUIcGF0aABsaXN0WzZdANAJDXVyaV9kcnN2AHNjb3JlPTAuMjQ5MQAQAGQAAAAEAAAA0AUHbmFtZQC2xePr1PMA0AQhdXJpADZiYjI4YzQ2OWE3ZDRhODJhMTI2NTVjZGY0MmZiMDQwANAFCHBhdGgAbGlzdFs3XQDQCQ11cmlfZHJzdgBzY29yZT0wLjIzMTUAEABkAAAABAAAANAFB25hbWUAwO7A9tXkANAEIXVyaQA2MWIyOWQ5MWYyYTY0ZTA1YjBmZGE1ZWVkN2Y2ODg1ZADQBQhwYXRoAGxpc3RbOF0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4yMjk1ABAAYgAAAAQAAADQBQVuYW1lALPJwfoA0AQhdXJpADE1ZjhmNjM5ZTYxMTRjN2FiMjAwMjZkOTg4ZTk3ZTY1ANAFCHBhdGgAbGlzdFs5XQDQCQ11cmlfZHJzdgBzY29yZT0wLjIxODMAEABlAAAABAAAANAFB25hbWUA1cXRp9PRANAEIXVyaQA1MmJlYmViNjZiNmY0MDhjODYwMTRlOWYxYzBhMTQzOADQBQlwYXRoAGxpc3RbMTBdANAJDXVyaV9kcnN2AHNjb3JlPTAuMjA2NwAQ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IXVyaQBjYzI1ZjhhYTU5Nzc0NjdiYjJlM2I0ZjVmOTlmZTNiNwDQCgdqdW1wcXVlcnkAt7bYqdipANAHFWFwcGVuZAC3trH5sfm13LXcsbvSycu9yfrX0wDQBzVwaWN1cmwAaHR0cDovL3QxMS5iYWlkdS5jb20vaXQvdT0yMTYzOTQ3NzUyLDMwNzY3NzkzNSZmbT01OADQBilpbWdpZABjYzI1ZjhhYTU5Nzc0NjdiYjJlM2I0ZjVmOTlmZTNiN18xMjFfMTIxABAA5QAAAAYAAADQBgllbmFtZQDJvb/asNm73QDQBCF1cmkAZTdmMTRlNWQzNTAzNGNmY2E2N2MzZDg0ZDBhY2M5OTUA0AoJanVtcHF1ZXJ5AMm9v9qw2bvdANAHFWFwcGVuZADIq8Pxxa7J8dLRseSzybfKyqbEzADQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0xODcyMTM3ODc0LDIwMTQ2MDA4MTUmZm09NTgA0AYpaW1naWQAZTdmMTRlNWQzNTAzNGNmY2E2N2MzZDg0ZDBhY2M5OTVfMTIxXzEyMQAQAN0AAAAGAAAA0AYFZW5hbWUA0Oy9vwDQBCF1cmkANTVhMDU1YjI1YTFmNDkyY2JiYTExMjA2NTQ1YTkwNjAA0AoFanVtcHF1ZXJ5ANDsvb8A0AcVYXBwZW5kANDH0q+4ycWutvnFrrTzyq6wy7HkANAHNnBpY3VybABodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTE4OTI0OTAzNzcsMTc5NTAzMDY1OSZmbT01OADQBilpbWdpZAA1NWEwNTViMjVhMWY0OTJjYmJhMTEyMDY1NDVhOTA2MF8xMjFfMTIxABAA5QAAAAYAAADQBgllbmFtZQDW3NDHs9vE6gDQBCF1cmkANjA1NzA2N2VlNDY4NDdkMGI0ZTRmM2RmZjBiZDk0YjYA0AoJanVtcHF1ZXJ5ANbc0Mez28TqANAHFWFwcGVuZAAxOTkyxOrQx9Kv1/fGt7Gst6LE6gDQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0xODI4NTQ0MDcwLDIwODI3MDk5OTAmZm09NTgA0AYpaW1naWQANjA1NzA2N2VlNDY4NDdkMGI0ZTRmM2RmZjBiZDk0YjZfMTIxXzEyMQAQANcAAAAGAAAA0AYFZW5hbWUAtcuzrADQBCF1cmkANGE5YTg2OTYwNjgwNDBmYzkzODMxZDRiODkxYzNlYjEA0AoFanVtcHF1ZXJ5ALXLs6wA0AcRYXBwZW5kANbQufrW+MP70rvP39Ow0McA0Ac0cGljdXJsAGh0dHA6Ly90MTAuYmFpZHUuY29tL2l0L3U9MzAyODc2OTUxNCwxOTE1NTU5NCZmbT01OADQBilpbWdpZAA0YTlhODY5NjA2ODA0MGZjOTM4MzFkNGI4OTFjM2ViMV8xMjFfMTIxABAA3QAAAAYAAADQBgdlbmFtZQC6zs7Eu9QA0AQhdXJpADBhNGEyMDJiNWY5ZjQ1ZDY4ZWRkNDUzYzMyYjc0MTVkANAKB2p1bXBxdWVyeQC6zs7Eu9QA0AcRYXBwZW5kAMnZwdbX48fy0rvF2rb4uuwA0Ac2cGljdXJsAGh0dHA6Ly90MTIuYmFpZHUuY29tL2l0L3U9MjQ5MDI2MTk5NSwyNDIwMzE5MzQyJmZtPTU4ANAGKWltZ2lkADBhNGEyMDJiNWY5ZjQ1ZDY4ZWRkNDUzYzMyYjc0MTVkXzEyMV8xMjEAEADhAAAABgAAANAGB2VuYW1lANXFzsC9oQDQBCF1cmkAYWU1N2QxODBiZmM4NDlmYWJiZTk5NjQ3MGJmZTM1YzYA0AoHanVtcHF1ZXJ5ANXFzsC9oQDQBxVhcHBlbmQAztLKx9Hdy7W80tbQtaPIzrW8yqYA0Ac2cGljdXJsAGh0dHA6Ly90MTAuYmFpZHUuY29tL2l0L3U9MTk3NDU4NzE1NCwyMzU0MTQ0NzU1JmZtPTU4ANAGKWltZ2lkAGFlNTdkMTgwYmZjODQ5ZmFiYmU5OTY0NzBiZmUzNWM2XzEyMV8xMjEAEADeAAAABgAAANAGB2VuYW1lANXUsb7LrgDQBCF1cmkAMzljZGU3OGI2MWYzNDZiNTkzMTQ1Y2QxZDE2YjIxZWYA0AoHanVtcHF1ZXJ5ANXUsb7LrgDQBxNhcHBlbmQA07LG+Lmmv9q8vMDWxvfR3dSxANAHNXBpY3VybABodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTc3ODYyMzI2OSwyMDA5NTI3NTE1JmZtPTU4ANAGKWltZ2lkADM5Y2RlNzhiNjFmMzQ2YjU5MzE0NWNkMWQxNmIyMWVmXzEyMV8xMjEAEADfAAAABgAAANAGB2VuYW1lANXFvNK71ADQBCF1cmkANDIxMGVjZWY4NTMyNDgzMTkyMmY0ZGM1M2QwYWUwZmMA0AoHanVtcHF1ZXJ5ANXFvNK71ADQBxRhcHBlbmQA0+u3orjns/bR3bDEw8W359TGMgDQBzVwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0zMTc1MDcyNjIzLDkzODIwMzcwOSZmbT01OADQBilpbWdpZAA0MjEwZWNlZjg1MzI0ODMxOTIyZjRkYzUzZDBhZTBmY18xMjFfMTIxABAA3wAAAAYAAADQBgdlbmFtZQDMt9O99+sA0AQhdXJpADllYTk4MTFjZDEzZTQwMGZiNjI3NDkwN2M0YWJlNDc5ANAKB2p1bXBxdWVyeQDMt9O99+sA0AcTYXBwZW5kAM/juNvR3dLVyMvQrbvhu+GzpADQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0zNTAxODk4MzQxLDM4MDEyNzMxMTMmZm09NTgA0AYpaW1naWQAOWVhOTgxMWNkMTNlNDAwZmI2Mjc0OTA3YzRhYmU0NzlfMTIxXzEyMQAQAN0AAAAGAAAA0AYHZW5hbWUA1cW+++W4ANAEIXVyaQAxOTFkOWNhOWJmYjY0NjliOGNjMmQ4NmY4MjY4MTM5YwDQCgdqdW1wcXVlcnkA1cW+++W4ANAHEWFwcGVuZADMqM3ltdrSu8b41srDwMWuANAHNnBpY3VybABodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTI1Njk1ODkzNDEsMTYzMTU1NjYxOCZmbT01OADQBilpbWdpZAAxOTFkOWNhOWJmYjY0NjliOGNjMmQ4NmY4MjY4MTM5Y18xMjFfMTIxABAA4QAAAAYAAADQBgllbmFtZQDLxNChzOzN9QDQBCF1cmkAMTk5MjU2ZTdiZTlkNGFjZThlYzcyMTI1OTdkMzA3ODEA0AoJanVtcHF1ZXJ5AMvE0KHM7M31ANAHEWFwcGVuZADT6cDWyKbX7snxtcTJ8buwANAHNnBpY3VybABodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTIwMTA3NTA1OTQsMzM0Mjg0NjM4NCZmbT01OADQBilpbWdpZAAxOTkyNTZlN2JlOWQ0YWNlOGVjNzIxMjU5N2QzMDc4MV8xMjFfMTIxABAA3wAAAAYAAADQBgdlbmFtZQC7xsql0sAA0AQhdXJpAGNmZmFlZWM2ZjQwNjQ5NTJhZmUzMTAzN2U3OTAzZTQwANAKB2p1bXBxdWVyeQC7xsql0sAA0AcTYXBwZW5kANOwytO46MnMtuDG3MWu0tXIywDQBzZwaWN1cmwAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0zNzAyMDE4MDI2LDMyNDQwNzU3NzImZm09NTgA0AYpaW1naWQAY2ZmYWVlYzZmNDA2NDk1MmFmZTMxMDM3ZTc5MDNlNDBfMTIxXzEyMQAQANkAAAAGAAAA0AYHZW5hbWUAstS+rtPFANAEIXVyaQBjMDNjY2I2OWI0ODA0YzllYjMzOWZiMjg2ODZjMDcwZgDQCgdqdW1wcXVlcnkAstS+rtPFANAHD2FwcGVuZACxyLOk1PPRxcPA0NS40ADQBzRwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0yOTk3MDIwNTIsNTEwMjUzMjg3JmZtPTU4ANAGKWltZ2lkAGMwM2NjYjY5YjQ4MDRjOWViMzM5ZmIyODY4NmMwNzBmXzEyMV8xMjEAEADdAAAABgAAANAGBWVuYW1lANXFw/QA0AQhdXJpAGRkNmU2YjI3ZjYzNDQ2OTE5NGE1N2UwMDFjNWQ5NmYyANAKBWp1bXBxdWVyeQDVxcP0ANAHFWFwcGVuZADSu7T6xNDTsMPUtcTDztbQx+nIywDQBzZwaWN1cmwAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0xNTI2NTExNDA0LDQyNzc5NjczOTgmZm09NTgA0AYpaW1naWQAZGQ2ZTZiMjdmNjM0NDY5MTk0YTU3ZTAwMWM1ZDk2ZjJfMTIxXzEyMQAUD2l0ZW0jbnVtI2JhaWR1ABAAAADQCwJzbGlkZV90eXBlADEA0AwCYXBwZW5kX3R5cGUAMgAQADQPAAAJAAAA0AYJdGl0bGUAz+O428P30McA0ARCdXJsAGh0dHA6Ly93d3cuYmFpZHUuY29tL3M/d2Q9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnNyY2lkPTIxMDI4ANADB2NxAMH1tcK7qgAgCjUAAAB0aXRsZWluZm8AAQAAABAAKwAAAAIAAADQBwlhcHBlbmQAz+O428P30McA0AoHanVtcHF1ZXJ5AMH1tcK7qgAUFHRpdGxlaW5mbyNudW0jYmFpZHUAAQAAACAFKA4AAGl0ZW0AEAAAABAA4QAAAAYAAADQBgdlbmFtZQC5xczswNYA0AQhdXJpADJiNmE2ZmFmMGQwNzQ1ZmFhMDJkM2Q4NWI1NTU2MDU4ANAKB2p1bXBxdWVyeQC5xczswNYA0AcVYXBwZW5kADIwMTXE6s/juNu159Owvdq088q5ANAHNnBpY3VybABodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTM3MTQ0NjkwMjcsMzQ1MTY0OTE0NCZmbT01OADQBilpbWdpZAAyYjZhNmZhZjBkMDc0NWZhYTAyZDNkODViNTU1NjA1OF8xMjFfMTIxABAA4QAAAAYAAADQBgdlbmFtZQDN9dfmz80A0AQhdXJpADA1NjAzMmRlZTIwNDRmNTdiNTIwNzk2MzNkYzFjY2Q5ANAKB2p1bXBxdWVyeQDN9dfmz80A0AcVYXBwZW5kAMvY0dXH5bS/xa7J8bK7wM+0q8bmANAHNnBpY3VybABodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTI2NDYyOTc3MTksMTk5MjAwNTcwMiZmbT01OADQBilpbWdpZAAwNTYwMzJkZWUyMDQ0ZjU3YjUyMDc5NjMzZGMxY2NkOV8xMjFfMTIxABAA3AAAAAYAAADQBgdlbmFtZQC5+bi7s8cA0AQhdXJpAGNiNmNlYjZkNThkMTQxODViMDBhYmI4NzhkZGRhNTg5ANAKB2p1bXBxdWVyeQC5+bi7s8cA0AcRYXBwZW5kAL75zqrP47jby8S088zszfUA0Ac1cGljdXJsAGh0dHA6Ly90MTAuYmFpZHUuY29tL2l0L3U9MTE3MjM3MDQwOCw3MTQ1MTMyMTYmZm09NTgA0AYpaW1naWQAY2I2Y2ViNmQ1OGQxNDE4NWIwMGFiYjg3OGRkZGE1ODlfMTIxXzEyMQAQAN0AAAAGAAAA0AYHZW5hbWUAs8LDwOf3ANAEIXVyaQBmODc1Y2I4ZGJhNjc0YjY3YmI1ZjM2MGNlN2Y1Y2E4NADQCgdqdW1wcXVlcnkAs8LDwOf3ANAHE2FwcGVuZACw18Tv19PW0MfOwPa1xNChx+AA0Ac0cGljdXJsAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9MjQ0NTk2OTcsMjUxNjcxOTkxMiZmbT01OADQBilpbWdpZABmODc1Y2I4ZGJhNjc0YjY3YmI1ZjM2MGNlN2Y1Y2E4NF8xMjFfMTIxABAA1wAAAAYAAADQBgVlbmFtZQDW7NLwANAEIXVyaQA0ODY0ZGY2NTg2N2I0YTUwOWU3N2M5YzY1MTg1NjQ5OADQCgVqdW1wcXVlcnkA1uzS8ADQBxFhcHBlbmQAtPO7sM73087Xz8+8z8nX0wDQBzRwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0xNjc3NzQ4OCwyMTI2NDE3NDU4JmZtPTU4ANAGKWltZ2lkADQ4NjRkZjY1ODY3YjRhNTA5ZTc3YzljNjUxODU2NDk4XzEyMV8xMjEAEADaAAAABgAAANAGB2VuYW1lAMG6vNK71ADQBCF1cmkAZjNmOTJkOGY2MzE5NDQ4YWEyNmMwOGZiZmRiYjQ4YzUA0AoHanVtcHF1ZXJ5AMG6vNK71ADQBw9hcHBlbmQAy8S97L3wz/G9sdOwtdsA0Ac1cGljdXJsAGh0dHA6Ly90MTIuYmFpZHUuY29tL2l0L3U9Mzk3OTk0MjY5MSw3NDI1ODM4MjMmZm09NTgA0AYpaW1naWQAZjNmOTJkOGY2MzE5NDQ4YWEyNmMwOGZiZmRiYjQ4YzVfMTIxXzEyMQAQAN0AAAAGAAAA0AYHZW5hbWUA1tzI87eiANAEIXVyaQBmMjI3ZmJkMWI0MTE0MmJkYTdlZjliZDNhMzJmZmRjNADQCgdqdW1wcXVlcnkA1tzI87eiANAHE2FwcGVuZADNrMH1tcK7qtb30d29rbr+x+kA0Ac0cGljdXJsAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9NzkxNjE4ODMsMjYwMjkxNDc3OSZmbT01OADQBilpbWdpZABmMjI3ZmJkMWI0MTE0MmJkYTdlZjliZDNhMzJmZmRjNF8xMjFfMTIxABAA2QAAAAYAAADQBgdlbmFtZQC2xePr1PMA0AQhdXJpADZiYjI4YzQ2OWE3ZDRhODJhMTI2NTVjZGY0MmZiMDQwANAKB2p1bXBxdWVyeQC2xePr1PMA0AcNYXBwZW5kALP20d2wxMPFt+fUxgDQBzZwaWN1cmwAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0zMDQyNTExMjQ0LDM5MTM2MjAzNDgmZm09NTgA0AYpaW1naWQANmJiMjhjNDY5YTdkNGE4MmExMjY1NWNkZjQyZmIwNDBfMTIxXzEyMQAQAOAAAAAGAAAA0AYHZW5hbWUAwO7A9tXkANAEIXVyaQA2MWIyOWQ5MWYyYTY0ZTA1YjBmZGE1ZWVkN2Y2ODg1ZADQCgdqdW1wcXVlcnkAwO7A9tXkANAHFWFwcGVuZAC008j9vLbR3tDHtb298MLt07C68wDQBzVwaWN1cmwAaHR0cDovL3QxMS5iYWlkdS5jb20vaXQvdT0xNzM2MjkxMjE1LDcyODkwNjE1MyZmbT01OADQBilpbWdpZAA2MWIyOWQ5MWYyYTY0ZTA1YjBmZGE1ZWVkN2Y2ODg1ZF8xMjFfMTIxABAA3QAAAAYAAADQBgVlbmFtZQCzycH6ANAEIXVyaQAxNWY4ZjYzOWU2MTE0YzdhYjIwMDI2ZDk4OGU5N2U2NQDQCgVqdW1wcXVlcnkAs8nB+gDQBxVhcHBlbmQAufq8yrmmt/K+3tDHvLC0yMnGvNIA0Ac2cGljdXJsAGh0dHA6Ly90MTAuYmFpZHUuY29tL2l0L3U9MzQ5OTMxMjI2NiwzOTM0NjEyMzU4JmZtPTU4ANAGKWltZ2lkADE1ZjhmNjM5ZTYxMTRjN2FiMjAwMjZkOTg4ZTk3ZTY1XzEyMV8xMjEAEADaAAAABgAAANAGB2VuYW1lANXF0afT0QDQBCF1cmkANTJiZWJlYjY2YjZmNDA4Yzg2MDE0ZTlmMWMwYTE0MzgA0AoHanVtcHF1ZXJ5ANXF0afT0QDQBxFhcHBlbmQAvvnOqs/juNvLxLTzzOzN9QDQBzNwaWN1cmwAaHR0cDovL3QxMS5iYWlkdS5jb20vaXQvdT02NjMwNTQ3LDI5NTE0OTIwMDgmZm09NTgA0AYpaW1naWQANTJiZWJlYjY2YjZmNDA4Yzg2MDE0ZTlmMWMwYTE0MzhfMTIxXzEyMQAQANUAAAAGAAAA0AYHZW5hbWUA1cW5+sjZANAEIXVyaQBjNTFmNjhiYmY3YjY0NTdiOGQ1MDIzZWU4YTg0YTZmYQDQCgdqdW1wcXVlcnkA1cW5+sjZANAHCWFwcGVuZADJ+sewusPT0QDQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0zMzQ0OTU0MDA0LDQyMTYwMjc3MjMmZm09NTgA0AYpaW1naWQAYzUxZjY4YmJmN2I2NDU3YjhkNTAyM2VlOGE4NGE2ZmFfMTIxXzEyMQAQAN0AAAAGAAAA0AYHZW5hbWUA1tO6usG8ANAEIXVyaQAyNjA4OGEzZjRiYTA0Y2FhOTBjZDI0ODUzODRlMDIxZQDQCgdqdW1wcXVlcnkA1tO6usG8ANAHEWFwcGVuZADT0LjozLPQocyr0fTWrrPGANAHNnBpY3VybABodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTM0MDE4MjI5ODIsMTk5NDY1Mzg5MyZmbT01OADQBilpbWdpZAAyNjA4OGEzZjRiYTA0Y2FhOTBjZDI0ODUzODRlMDIxZV8xMjFfMTIxABAA3wAAAAYAAADQBgdlbmFtZQDZ3MqrwvwA0AQhdXJpAGJmMGMxOGU3MmU5NzQ0NjlhZDJmOWMxZmU2YTA3NGU0ANAKB2p1bXBxdWVyeQDZ3MqrwvwA0AcVYXBwZW5kAM3yx6fQx7vU1+680cWu1ve9x72xANAHNHBpY3VybABodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTQyNDI4MjIxNTQsNTkyMTE1NTcmZm09NTgA0AYpaW1naWQAYmYwYzE4ZTcyZTk3NDQ2OWFkMmY5YzFmZTZhMDc0ZTRfMTIxXzEyMQAQAOAAAAAGAAAA0AYHZW5hbWUA1dTRxdalANAEIXVyaQA0NDY1N2ExNmU1NTA0MjNmODY2YjQ5ZGI5MmQwMDgwOADQCgdqdW1wcXVlcnkA1dTRxdalANAHFWFwcGVuZADW0Ln6u6q2pr2xse3R3dLVyvW80gDQBzVwaWN1cmwAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT00MDE1MzkzNDYzLDcxMjE4Mjg2MyZmbT01OADQBilpbWdpZAA0NDY1N2ExNmU1NTA0MjNmODY2YjQ5ZGI5MmQwMDgwOF8xMjFfMTIxABAA2gAAAAYAAADQBgdlbmFtZQC66b3wsaYA0AQhdXJpADJmZmFjZGU5ODE3ZTQ5MGM4OGNkODZjZWVhMjFlMWViANAKB2p1bXBxdWVyeQC66b3wsaYA0AcPYXBwZW5kALT6se3X97fJwfrDzb2rANAHNXBpY3VybABodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTE2MDY3MjQwNTMsNDI1MDM0OTU4JmZtPTU4ANAGKWltZ2lkADJmZmFjZGU5ODE3ZTQ5MGM4OGNkODZjZWVhMjFlMWViXzEyMV8xMjEAFA9pdGVtI251bSNiYWlkdQAQAAAA0AsCc2xpZGVfdHlwZQAxANAMAmFwcGVuZF90eXBlADIAFA9jYXJkI251bSNiYWlkdQACAAAAFAdTaXRlSWQAJFIAAA==\u0000"},{"ResultURL":"demo_mola_service","Weight":0,"TimingNeed":0,"DisplayData":"EACgqwAADAAAABQHU3RkU3RnAG5SAAAUB1N0ZFN0bAAIAAAA0A0LX3VwZGF0ZV90aW1lADE0Mjc5NjkxODcA0AQ+bG9jAGh0dHA6Ly9vcGVuLmJhaWR1LmNvbS9xP3I9MjExMDImaz0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUA0AQHa2V5AMH1tcK7qgDQBEJ1cmwAaHR0cDovL3d3dy5iYWlkdS5jb20vcz93ZD0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmc3JjaWQ9MjEwMzgAIAWEAAAAbGlzdAAgAAAA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQDQAAEA0AABANAAAQAUD2xpc3QjbnVtI2JhaWR1ACAAAABQBbgHAABkcnN2AGNhcmRzX2luZm97ZX1leUpsWWpsa016TTROakJtTnpCalpXTTVPVFptTkRNeFlUWXpaREl4WmpnNU1TSTZXemdzZXlJMU1qSXlNelZoTVRneU1qSTBNVGc0WW1Sall6QmhZamRrTW1SaU9HTmlZU0k2V3lKY2RUaGtOelZjZFRZM01tTmNkVFZqTnpFaUxDSmNkVFJsWlROY2RUZzROamhjZFRSbU5XTmNkVFUwWXpGY2RUUmxOakZjZFRZM05URmNkVGN5TXpGY2RUWXdZelVpWFN3aU1HRTBZVEl3TW1JMVpqbG1ORFZrTmpobFpHUTBOVE5qTXpKaU56UXhOV1FpT2xzaVhIVTBaalUxWEhVMk5UZzNYSFU0WmpnNUlpd2lYSFUxWmpjeFhIVTRPV00yWEhVMlpqRTBYSFUxTkRVNElsMHNJbUUxT0dZNE1UYzFaVFJoTURSa01tRTROREV5TXpVM05qQTBNV1E0WVRRMklqcGJJbHgxTldNd1pseDFOV013Wmx4MU5XWmtOeUlzSWx4MU5HVTVZVngxTm1Rek1seDFOV013Wmx4MU5qVmpZbHgxT1RoalpWeDFOamM1TjF4MU5XWmtOMXgxT1RnNU5seDFOR1UwWWx4MU5XSTFNQ0pkTENJeE5UZzNaalExWTJVMk9UYzBNRE5oWVRrMk9EaG1OelJsTkRZeU5UVXhaU0k2V3lKY2RUbGhaRGhjZFRVM01EWmNkVFUzTURZaUxDSmNkVGhrTnpWY2RUVXpZemhjZFRWbFpqZGNkVFJsTkdKY2RUVTVZbUpjZFRVMlptUmNkVFpqTVRGY2RUVTVOek5jZFRjNU5XVWlYU3dpTXpsalpHVTNPR0kyTVdZek5EWmlOVGt6TVRRMVkyUXhaREUyWWpJeFpXWWlPbHNpWEhVNFpEYzFYSFUyTnpKalhIVTJZek0wSWl3aVhIVTNPRFpqWEhVMll6RTBYSFUxTWpsbVhIVTFNMlV6WEhVMk1qZ3dYSFUwWlRVd1hIVTFOalk0WEhVMlpqRTBYSFUxTkRVNElsMHNJbVZqWXpneFpqa3dObVl3WlRReVpEazVaamsyWW1SaE1UTTBNakl5TkRsbUlqcGJJbHgxTnpNNFlseDFOVE0wTTF4MU5tVTVNQ0lzSWx4MU9EQm1aRngxTmpJNFlWeDFPVEUwWkZ4MU9EbGtNbHgxTm1ZeE5GeDFOVEZtWVZ4MU5HVXpZbHgxT0Rsa01seDFPVGhqWlZ4MU9URmpOeUpkTENJM05UTTJZVEpoWW1abFlXSTBNRGs0WW1KbE9EY3dZelZqTW1FME9UVXhNaUk2V3lKY2RUWTNOV05jZFRZMVpXUmNkVFJsTVdNaUxDSmNkVFZtTnpGY2RUZzVZelpjZFRabU1UUmNkVFUwTlRnaVhTd2laVGxqWm1JeU16WXpOekl3TkdVME16aGpZakF4TnpBd01UazJOR1JpTlRJaU9sc2lYSFU1TmpRNFhIVTBaakZtWEhVNU56QTJJaXdpWEhVMFpXVXpYSFU0T0RZNFhIVTBaalZqWEhVMU5HTXhYSFUyTURSaVhIVTBaV0poWEhVM1pEWmxYSFU0WW1Wa0lsMTlMQ0pjZFRjMlpqaGNkVFV4TnpOY2RUUmxZbUZjZFRjeU5qa2lMREZkTENJek9ESXdZekUzWXpVMU1XWXhabU0xTW1VME1qSmlaVEV6TmpjME16ZGhOU0k2V3pRc2V5SmhNRE5qWW1ZeE5qQmtZalkwWVRoallUSmtPRGxpT0RNd056ZGpZbUprWkNJNld5SmNkVFkyWm1WY2RUWmpOV1lpTENKY2RUZ3dNREZjZFRZeU1HWmNkVGxoWVRoY2RUVXhOamhjZFRnd1ptUmNkVFptTVRSY2RUVTBOVGdpWFN3aU5UZzVOVEl5TUdWbVpHVmhORGRoWW1FeE9HTTBZakV4WkRJNU9HTXhPR01pT2xzaVhIVTVOalE0WEhVNE16Vm1YSFU0TTJJeUlpd2lYSFUxTkRZNFhIVTJaR0UyWEhVMU0yUXhYSFUzTmpnMFhIVTFPV0ppWEhVMVlqVXdJbDBzSW1FNFpUWTROREl5WkRaa09UUmhOakJoWm1KaU56WTRZamRrTldObU9XRTVJanBiSWx4MU5qWXlOVngxTmpZMVlWeDFPV1ZrTVZ4MU9ESTNNbHgxTkdVd09WeDFOVEl3Tmx4MU9UUTVaaUlzSWx4MU5Ua3laVngxT0Rsak5seDFOall5TlZ4MU5qWTFZVngxTnpZNE5GeDFOR1V3TUZ4MU5Ua3lOMXgxT0dReU5WeDFOMkl4TkNKZExDSmhOV0kyWVdFeU1XWXdNRE0wT1RrME9ETmtPVFJpTlRBeE9URXdOMlUxTmlJNld5SmNkVFkzTXpGY2RUUmxNMlJjZFRVd01qa2lMQ0l4TWx4MU5XVTNORngxTkdVellWeDFOVEl4T0Z4MU5XWmlOMXgxTlRNMFpWeDFOR1ZoTjF4MU5HVXdZbHgxTkdVd01GeDFOVGszTXlKZGZTd2lYSFUxTVRjMlhIVTBaV1EyWEhVMFpXSmhYSFU0Wm1RNFhIVTJOREZqSWl3eFhYMD17c31zaG93X3JlYXNvbntlfTEAEBB9gwAAUmlnaHRfUmVzb3VyY2VzAAQAAADQBEJ1cmwAaHR0cDovL3d3dy5iYWlkdS5jb20vcz93ZD0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmc3JjaWQ9MjEwMzgAIAUDgwAAY2FyZAACAAAAEABbTgAADAAAACAFpgYAAHVuaXQAEAAAABAAZAAAAAQAAADQBQduYW1lAM31x6fUtADQBCF1cmkAZWNjODFmOTA2ZjBlNDJkOTlmOTZiZGExMzQyMjI0OWYA0AUIcGF0aABsaXN0WzBdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDIyNQAQAGQAAAAEAAAA0AUHbmFtZQC2xdDxtqsA0AQhdXJpADc1MzZhMmFiZmVhYjQwOThiYmU4NzBjNWMyYTQ5NTEyANAFCHBhdGgAbGlzdFsxXQDQCQ11cmlfZHJzdgBzY29yZT0wLjAyMTIAEABkAAAABAAAANAFB25hbWUAus7OxLvUANAEIXVyaQAwYTRhMjAyYjVmOWY0NWQ2OGVkZDQ1M2MzMmI3NDE1ZADQBQhwYXRoAGxpc3RbMl0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMTkwABAAZAAAAAQAAADQBQduYW1lANXUsb7LrgDQBCF1cmkAMzljZGU3OGI2MWYzNDZiNTkzMTQ1Y2QxZDE2YjIxZWYA0AUIcGF0aABsaXN0WzNdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDE4OQAQAGQAAAAEAAAA0AUHbmFtZQDV1LG+yb0A0AQhdXJpADUyMjIzNWExODIyMjQxODhiZGNjMGFiN2QyZGI4Y2JhANAFCHBhdGgAbGlzdFs0XQDQCQ11cmlfZHJzdgBzY29yZT0wLjAxODUAEABkAAAABAAAANAFB25hbWUAs8LOsPaqANAEIXVyaQBlOWNmYjIzNjM3MjA0ZTQzOGNiMDE3MDAxOTY0ZGI1MgDQBQhwYXRoAGxpc3RbNV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMTg0ABAAZAAAAAQAAADQBQduYW1lALjf1LLUsgDQBCF1cmkAMTU4N2Y0NWNlNjk3NDAzYWE5Njg4Zjc0ZTQ2MjU1MWUA0AUIcGF0aABsaXN0WzZdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDE3OAAQAGQAAAAEAAAA0AUHbmFtZQDQodCh1r4A0AQhdXJpAGE1OGY4MTc1ZTRhMDRkMmE4NDEyMzU3NjA0MWQ4YTQ2ANAFCHBhdGgAbGlzdFs3XQDQCQ11cmlfZHJzdgBzY29yZT0wLjAxNzIAEABkAAAABAAAANAFB25hbWUAy9XT0MXzANAEIXVyaQBlMDhmOWQyOGRiZWE0YmNhOTkyZmRlMDQ0M2ZjMWM2MADQBQhwYXRoAGxpc3RbOF0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMTY2ABAAZAAAAAQAAADQBQduYW1lALbF3si64gDQBCF1cmkAZTFlYTY4OTIxYjc0NGRhMjk5MWE0YzI1YzI5NTk3OTYA0AUIcGF0aABsaXN0WzldANAJDXVyaV9kcnN2AHNjb3JlPTAuMDE2NQAQAGMAAAAEAAAA0AUFbmFtZQDL79mzANAEIXVyaQA1ZTc4M2ZmY2Q2ZmE0NDRiYWZiYjIwZWM1OWY4NDk5MgDQBQlwYXRoAGxpc3RbMTBdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDE2MwAQAGUAAAAEAAAA0AUHbmFtZQDVxbzSu9QA0AQhdXJpADQyMTBlY2VmODUzMjQ4MzE5MjJmNGRjNTNkMGFlMGZjANAFCXBhdGgAbGlzdFsxMV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMTYwABAAZQAAAAQAAADQBQduYW1lAMLt0sGsUADQBCF1cmkAOWJhMzE4NjViNWQ0NGU2YTllMjhjZTAwMjI1YjIzNmMA0AUJcGF0aABsaXN0WzEyXQDQCQ11cmlfZHJzdgBzY29yZT0wLjAxNTkAEABlAAAABAAAANAFB25hbWUA1tzI87eiANAEIXVyaQBmMjI3ZmJkMWI0MTE0MmJkYTdlZjliZDNhMzJmZmRjNADQBQlwYXRoAGxpc3RbMTNdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDE1OQAQAGUAAAAEAAAA0AUHbmFtZQDX3tXXwfoA0AQhdXJpADliODk3MDU2Mzg5YjQ3MjNhMWE2NWVmNzE2ZDYxNGQ4ANAFCXBhdGgAbGlzdFsxNF0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMTU5ABAAYwAAAAQAAADQBQVuYW1lALr6uOgA0AQhdXJpAGZhNTIyNjIzNjBkYjQzNDk5ZGE0MTQwNjIxNTA3YjU3ANAFCXBhdGgAbGlzdFsxNV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMTU4ABQPdW5pdCNudW0jYmFpZHUAEAAAANAJBmNhcmR0eXBlAHJlY29tANAHIWNhcmRpZABlYjlkMzM4NjBmNzBjZWM5OTZmNDMxYTYzZDIxZjg5MQDQCQlzdWJ0aXRsZQDP4LnYyMvO7wDQBEJ1cmwAaHR0cDovL3d3dy5iYWlkdS5jb20vcz93ZD0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmc3JjaWQ9MjEwMzgA0AgCc2hvd3JvdwAyANAJAnNob3dudW1zADgAIAVzRgAAbGlzdAAQAAAAEACJCAAACwAAANAFB25hbWUAzfXHp9S0ANAENmltZwBodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTM5MTMwMjI2NTksMzgwNzI2MzQ0NiZmbT01OADQB11wYXJhbXMAd2Q9JUU3JThFJThCJUU1JThEJTgzJUU2JUJBJTkwJnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMzgA0AQHdGlwAM31x6fUtADQBRVhdHRyAMTcsNHF5L3H0d2z9tb3vce357LJANAJBGF0dHJ0eXBlAFRBRwBQCNwGAABhdHRycGljAGRhdGE6aW1hZ2UvanBlZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVvQUFBQW9DQVlBQUFCWjdHd2dBQUFFMmtsRVFWUjQydTJaTWJhck5oUkY5OC82WmRheU9wZW9vNlRVRENBamVNeEFnOUlNOEFnaStoUXFLZWxFNlU0ZXdVc0JHREN5RGYvbHBVaFFZeHN3U09lZWUrN1Y0Y2ZuNStjbngzZzdmanNnT0lBNmdEcUFPb0E2Z1ByZmpKL2JMdzI0NmtKUW1rS09oeHlWTzFNV3N2OSthUkQ1Y041YnFxdWlWQUp2RFhVWHUyZENyZ3Q0ZGo3SnlFSkRjeHNQbk1nK1NwU1lMdkhXMEthek9jV0d0NWdhY2wwd3Z5eTRpb3VYZkpRSzhXYjFQN2IyVWQ1V1hGV0pFaDVyV2xKZElBZHdiZ0NuYlBuQUI2RDZ4UVJjWmFGNHVNOWkwVG00S3lveStXa09zNFZPS000QXp0RXI1RHpXMUhSdjFwbmtjZEIvYmdOcGlIaG5hSVpqbmZWbzlUQ3A0S2pjNzhqdzE4Q0NEdE1rSk1uYkIyQkdTblYxLzJFYVR0a0hwUkl2NXBTUTYzSmlTWEJVbDRDSzBrdFNhUDJTZ2NGVnVLK2tuaXcwT3JJNDJ6NHNJZ1FRS2FyUXFFZEc4VGFVNURpdVNoSHNsVlQ2cDVPZVVybWpObVoxL241c1lIbXdCaWQ2MEdXaEVhN0MxTGZOYk5xdVVmTVVXOUFickttWnp6WEppK2d0dXRwd3Yrd3lNak1odlY5eDVScml1cmpRS0RVRXpsdE1tMDVzZnZ5TngxYlhlNkNGcXpCV29RdUpVR1dmRGNNMWFvTkdiUmZ6dVFaNWkya25PajhidCtaeVQ3MTF0SHFObXBCc2FFNFpId0xjcmFGdTRKUk5naTlIalZxaXo1SlEzZkwzS1VNTlg0VXFoNnhZYTFWbm1oZmF0aGVvVzhObHZDRkFraTZqT0xDTzdBK2svNVBteGwxajRxa25LYlNNQ25DaE5jRlYySlVFbEl1cXRWallDMFl0Sy9RODZETkdCVWZsdm8xUnM2aWVNajYwN3MrclVhTjJOQ29yZG95TWVtRGhQRlYyTUNxMEhwRXF3SytDUG1mVTE0R0tNWXBZMVJ2NnFrMWpXTGhhMHo3R0tNS1ZjUDhhbHVuOGtsR0Ixb05JSDRQK2J6SXFVdlUyRDkvU2laU0M4SUpSZ1dzQUtmcjczMFRhTDdBUnBQcFZBWnBBSmJSNEpJV0lCLzJmWmRTREVKNHlCVElscWRkVmJ5emZwNndudmt3VDZublZZOTVwU3dqdEUwWUpVZ21YeTlTL0pYa0IzaEl5aFh6WGt5VTVZa2c3WklFZzRLcWFMdExoOS8rcnNUN2VJdnc0SE01alUzd0FkUUIxQUhVQWRSaDM3L2ZKRmU1Y3NxMjNuUHRRN3kyZHQwYmN3a0hZMFBkdGJIbm0rOHBmQnVvZE1IM2ZVenp4andTcVZGaGo4VThtTXQ1ajlMM01XeU11MGdzOWRQelBYWWhIbDFWVGZCZWpkdHN5OXk3WVJEMmcvVVpjekNZWlhkTTBFaWg5My9kRjdaWGc2RWtmWitIM0FDVVVwVmFyam5rMDhyNXF4SW1aQTZHazQyTFA2RUlTbkNOa0JaS3djaXVXS2QzL3o3cTBuODhZRUYwOFRkVmRRSFdyYmNqeTkzcTN2MjNzTmVLV01TbklxZ3ZXWllSR29MUUFRdlFaV0VOMTdhMGZvUXBrNWZBcXBSMUFrdjlFNmsydVlGeXpvcnY5dldPSGJiSklxeUs3dndHU2J3SnlQKzhkWGlvVUFxbmZWNlNOUUFWYzVUaVh6MUVYU2lHcWxxRFVzUG1NaVdmSDNLbFpwZEptSXk0c2JlTVF1QUczMW9PVU95cmt3M3hlVk12djBhaVZlTDdXcUY5amxPQXNCZ0JyeVBVSDErb1MzZjAvdmh3SnJzSjZRQWdnM2VTZmZSTlF2MUFvOXhoeG9jVWpTQWZiaENIbFpKa1BMVWdLdDBBSURqdXJaT043d042aWRuM2d6ZzVqNnBkdllIWUNGYXRJRCtJZTFaQnRQcGZiWWNTRjFuTVRDdUVkWG41UXlxa0tGbmxMNVVDZUF0Y2dRSndKMW5EcGVnOWZhekUrY3FRYld2ZnBhZW92cDE0a2xWNDBlYnMxUVlWZFJwd1BrQ2tKUXM1QW1oWmVTdURjWXVxR0pOZElHWGt2eWV2MFBJeTdZMU44QUhVQWRRRDFIeHgvQTJSa1RMQWhzeStJQUFBQUFFbEZUa1N1UW1DQwDQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpAGVjYzgxZjkwNmYwZTQyZDk5Zjk2YmRhMTM0MjIyNDlmANAHNmF0dHJpZABlY2M4MWY5MDZmMGU0MmQ5OWY5NmJkYTEzNDIyMjQ5ZiDE3LDRxeS9x9Hds/bW973Ht+eyyQDQBilpbWdpZABlY2M4MWY5MDZmMGU0MmQ5OWY5NmJkYTEzNDIyMjQ5Zl8xMjFfMTIxABAAcQUAAAsAAADQBQduYW1lALbF0PG2qwDQBDZpbWcAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0yNzU0NTY4NTc4LDE4OTQwODIxMzQmZm09NTgA0AddcGFyYW1zAHdkPSVFNiU5RCU5QyVFNiU5NyVBRCVFNCVCOCU5QyZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDM4ANAEB3RpcAC2xdDxtqsA0AUJYXR0cgDTsMrT0d3UsQDQCQRhdHRydHlwZQBUQUcAUAjcAwAAYXR0cnBpYwBkYXRhOmltYWdlL2pwZWc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFb0FBQUFVQ0FZQUFBQXFWS3YyQUFBQ21rbEVRVlI0MnUyWU81YmlNQkJGYjgrWkhHV0VLSE5JcUIxWU8wQTcwS0swQTdFRGVRY0tIVHFUUXpLekFpYnczeGlhbVRsMGQrQUs1YU5QWGIxNkpmaTQzVzQzdHZnMGZtMElObEFicUEzVUQ0N2Yvelc3aWZoenlYVTV2anR5TWdvQlFDSzRpc3hxSk5CRVQ5d2J0T3kvRmRTUDVxZUFLeUR2NW83YmVzNUpUdmFZeG9NMWh6amNyZmQrVUhkUXVvUDZTNThTMFJlUTIrRmdRaW53a1VaMmM1N05seHByRThFNWlydU5TODZ1SE5QUGJRZi9HWXoyMHI1ZVVRRFgrWUY3ZUlxRzZNOGtlY0xJSHRxWnNwTmY3ZUZrOW1NS3dYTlJCblVuRVltMmxoUWNWVGFGTVZkWW5JM1VGTTQ5VkZUMkxhQWVLS0lLSFNRbElBWDhSV0dNUmZXbDAreFh5bVp4LzhFUlJidUcxQllSUGE2NDNxYytVMU1MOW1kNTFETkY2UllLS2VDcURLdEZuejNuVXBCYkNhU25Tdzl3Z3NKcWlWQUdxOGJMVUNzZTFVVFB1YngrY3JmZEJYNFpLS0V3N2NsWFM2ZFZUcHZrWVA1RmE3TkZTRmo5eWhZRys4Q2s2LzZDRHZtNHg1M0M3bVRLWUtGZkEycnVPZDNKS2VjMU1Vc2d4WVRNajZScWo4a3FmQlJEWjZ6cUszVVR5U2ErTmNDTmU0eWVsdmxFVVUzRXgyZU5lZHBsdjZYMEJNcmtOSlBXUHlRV1FFL0xZaGd6eUNhMkJTYzFSaVpDdWtDcXFIYzdkbXVKVmdtUnFiWk1GMlUrVmRSRFVNMFY5ai9CbzlZNnpPNjRlR3MxS0t0WHpGdWlEUVJYY3NoemlKZHVUQTZxclJLSWJOazRYbFZVb3FxaHJoM2hXVG0rSDVSRUhYZXdONmlMSnlBUmlkRmtVOEJGd1drVjB2aGc1WGpDeUlZUTU1MVRhVWhJK2o3d2lxS0VNdWlKcVI5eWk1VnRCM1ZGLzhZU2Y1M3B4Ny8vemRLL2s0NklzcVR1VFZSRWZHZ1ExTlJpN2xFeno4bXF4YXQ3NFhtSG5KT0lCRFJHMFgzYmNUd3QzbG9wNElxYVEyNVJsN0hqUGU1c1hWTTRySnp0UGFDMkg4VmJiS0EyVUcrUFA1KzVoVjJYZi81b0FBQUFBRWxGVGtTdVFtQ0MA0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQA3NTM2YTJhYmZlYWI0MDk4YmJlODcwYzVjMmE0OTUxMgDQByphdHRyaWQANzUzNmEyYWJmZWFiNDA5OGJiZTg3MGM1YzJhNDk1MTIg07DK09Hd1LEA0AYpaW1naWQANzUzNmEyYWJmZWFiNDA5OGJiZTg3MGM1YzJhNDk1MTJfMTIxXzEyMQAQAHEFAAALAAAA0AUHbmFtZQC6zs7Eu9QA0AQ2aW1nAGh0dHA6Ly90MTIuYmFpZHUuY29tL2l0L3U9MjQ5MDI2MTk5NSwyNDIwMzE5MzQyJmZtPTU4ANAHXXBhcmFtcwB3ZD0lRTQlQkQlOTUlRTYlOTYlODclRTglQkUlODkmcnN2X2NxPSVFNSU4OCU5OCVFNSVCRSVCNyVFNSU4RCU4RSZyc3ZfZGw9MF9yaWdodF9yZWNvbV8yMTAzOADQBAd0aXAAus7OxLvUANAFCWF0dHIA07DK09Hd1LEA0AkEYXR0cnR5cGUAVEFHAFAI3AMAAGF0dHJwaWMAZGF0YTppbWFnZS9qcGVnO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRW9BQUFBVUNBWUFBQUFxVkt2MkFBQUNta2xFUVZSNDJ1MllPNWJpTUJCRmI4K1pIR1dFS0hOSXFCMVlPMEE3MEtLMEE3RURlUWNLSFRxVFF6S3pBaWJ3M3hpYW1UbDBkK0FLNWFOUFhiMTZKZmk0M1c0M3R2ZzBmbTBJTmxBYnFBM1VENDdmL3pXN2lmaHp5WFU1dmp0eU1nb0JRQ0s0aXN4cUpOQkVUOXdidE95L0ZkU1A1cWVBS3lEdjVvN2JlczVKVHZhWXhvTTFoempjcmZkK1VIZFF1b1A2UzU4UzBSZVEyK0ZnUWlud2tVWjJjNTdObHhwckU4RTVpcnVOUzg2dUhOUFBiUWYvR1l6MjByNWVVUURYK1lGN2VJcUc2TThrZWNMSUh0cVpzcE5mN2VGazltTUt3WE5SQm5VbkVZbTJsaFFjVlRhRk1WZFluSTNVRk00OVZGVDJMYUFlS0tJS0hTUWxJQVg4UldHTVJmV2wwK3hYeW1aeC84RVJSYnVHMUJZUlBhNjQzcWMrVTFNTDltZDUxRE5GNlJZS0tlQ3FES3RGbnozblVwQmJDYVNuU3c5d2dzSnFpVkFHcThiTFVDc2UxVVRQdWJ4K2NyZmRCWDRaS0tFdzdjbFhTNmRWVHB2a1lQNUZhN05GU0ZqOXloWUcrOENrNi82Q0R2bTR4NTNDN21US1lLRmZBMnJ1T2QzSktlYzFNVXNneFlUTWo2UnFqOGtxZkJSRFo2enFLM1VUeVNhK05jQ05lNHllbHZsRVVVM0V4MmVOZWRwbHY2WDBCTXJrTkpQV1B5UVdRRS9MWWhnenlDYTJCU2MxUmlaQ3VrQ3FxSGM3ZG11SlZnbVJxYlpNRjJVK1ZkUkRVTTBWOWovQm85WTZ6TzY0ZUdzMUtLdFh6RnVpRFFSWGNzaHppSmR1VEE2cXJSS0liTms0WGxWVW9xcWhyaDNoV1RtK0g1UkVIWGV3TjZpTEp5QVJpZEZrVThCRndXa1YwdmhnNVhqQ3lJWVE1NTFUYVVoSStqN3dpcUtFTXVpSnFSOXlpNVZ0QjNWRi84WVNmNTNweDcvL3pkSy9rNDZJc3FUdVRWUkVmR2dRMU5SaTdsRXp6OG1xeGF0NzRYbUhuSk9JQkRSRzBYM2JjVHd0M2xvcDRJcWFRMjVSbDdIalBlNXNYVk00ckp6dFBhQzJIOFZiYktBMlVHK1BQNSs1aFYyWGYvNW9BQUFBQUVsRlRrU3VRbUNDANAOAmF0dHJwaWNpc2xpbmsAMADQBCF1cmkAMGE0YTIwMmI1ZjlmNDVkNjhlZGQ0NTNjMzJiNzQxNWQA0AcqYXR0cmlkADBhNGEyMDJiNWY5ZjQ1ZDY4ZWRkNDUzYzMyYjc0MTVkINOwytPR3dSxANAGKWltZ2lkADBhNGEyMDJiNWY5ZjQ1ZDY4ZWRkNDUzYzMyYjc0MTVkXzEyMV8xMjEAEADdBwAACwAAANAFB25hbWUA1dSxvsuuANAENmltZwBodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTI3MzI2Mzc0ODksMjUyOTcyMjg1MSZmbT01OADQB11wYXJhbXMAd2Q9JUU4JUI1JUI1JUU2JTlDJUFDJUU2JUIwJUI0JnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMzgA0AQHdGlwANXUsb7LrgDQBRNhdHRyANOyxvi5pr/avLzA1sb30d3UsQDQCQRhdHRydHlwZQBUQUcAUAg0BgAAYXR0cnBpYwBkYXRhOmltYWdlL2pwZWc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFb0FBQUFvQ0FZQUFBQlo3R3dnQUFBRVhFbEVRVlI0MnUyWlBaS3JPQlNGdjU3cTNNcWNUQlhLSEx5QWtCM0FEdXdkYUZIYUFleEE1QzlRU0VnbVFtZGlCVDBCWUF0c01HNzc5VlROb01obEcvMGNuWHZ2dVllUHI2K3ZMN2J4Y1B5MVFiQUJ0UUcxQWJVQnRRSDF2eG1mYS83a2JVNVJ0ZXRtM01VY1R3a0N3Qm55YzhJcEVkL2IzY0x6em1qSzV0RldqdGRudlNVM2tBMTdXN0hHMDBDSjVJUktQTFpiaWRHY3N3dDVyRzFvMndaZHpjOGRwWXBEUFQxMFJLb3lKQ0QyWXZIWlRDNkIvTU9NR2c3dWtUMUlEcU5Mcm1lN2duSFp2Szl4SWtXZDVPT3BwVUxoc2JsbGYrb0FldWNJMlZkb1R4eDdxbEdFQkpjWnBhZzc2SzhHeWx1TGw5bVZ0a09JQll4eVJsTVBiRElPS1QxYWw4OHp3aG4waFdJYWZRMG00dU9FMFN1R3pCUnFFbnBKOGdkQ0R6eTFhMm5iQWwxQmxLYlFWaFNYYXdnWWRRQ2NwUklKS3BIWERUMTNNcFRxY3FNaDZ3L1JoLzZiR1RiZS96WGt2NW5NRFZYYjNlYmU5cXhaWUpTcklSWjJrVTF6RkwvSmozdnh2aGhzS3dydFNaVWlOVG5uSkdDbnQrUjJQeHYybit2WUpJZ2lmMmZSKzR5U1dYY3JzMnp5bHR5dVdObURPTHlLanNmbUJWVTdxY2dIUVdrZFNaZFF1MVNSSmEvb0tFRnl5aGp2VjNLSXV2S3Jqakc3S0VVcFJScTllcWlHVW11ME5qZ2NkU040blZDQzVLUzZmVTdDTzZYRU9IQ213TWxzTWZjOVVmVmFxa0lIckRseXpvZWNwUzVKYzFYRkVudUVQK01CbTUvNVcxVDhidnB3N0t1a014b2ZINFA1UEw0VkhONFlpVEpMcWJYR2hucnJkYUNtRmNmait3cmJsQWFubmluckFrR0p0VEZlN01reXhhOXBzaVZGUGRoOFU0WVY4WjdnVEI2SzZDaFZKTFZHNi9sRUR2RHh0SEYzS2QzaHhJR3VDdlBBaW5sRzZyblBKMDRPMzAzMFdsQUFuTkhVaDBlQ3N5c3lsODRpU2xISm1ieW80SVpGL1ZvelJlWmpjemkzcG5nRGFnTnFBMm9EYWpQdTN0ZDRodm9yYUNjQ0J5RTVUNHpCb0kvVUpUZjZ4dHVjd3NrWkdUSzFnRzZhekVXOTlNZUFtbk0vZC9FUmxZbkZqWHFiWTIvY1NJY1pIRGVab1pURGFNMXRleDMybWxQTFpnNE1oOUgxdjhlbzNZb1dZTnJQQlJxeTc3R0xxM20yaTBtQ3ZqSlRhbEZnaG9EZlcyTjZVZC9wczE4V25EY0hjQVpkSDFaWktNTWhPOC9KWTdSRkJHMlNNeG9ycnBjd3g5NUZTL2hONDBXZzd2am9DMEI5NXlVRk5xZnd5V1MrTGp5VE96bHF6UnJQUmNCYmdIcVVPSmR1dlh2V3gwY1NYM1JOOENJdEZ0WUsrak52Yyt6K3RLb0gvTUVjMWVXUG0yWjNobEZqQ3pZaVZZTXRvMURPakIzUm9mTDF6dU1wQ3h2dWdGRVBUTUNId1Ayb2puSUduVnY4SFdCeTZ3UC81MGk4R3lkYzQ1aThUQmc3RUw1MmlJTWNNajZGMW1oZDBneWZpNHFsUVBPK2Zjc1IzeU1QWmpTTnpCVEM1dWc4L1AwSmVZQ25kb0VkL0RTakhIVURUYU14THliOHo5ZUkxRlVsZFpxUGQ1R2NVSHVETnE3WFZVL0lBMS9qa0Z6a1dEdldUczMxWmVKb3ZXeGl6Q25aN2JXTDdJaFVpWjhGS3JSK3cyb1RwZG4wanlqWk1lUVpSdm5hZ2N3UWVHeGUwdHg3citjTXVpd3hicXp3ZC9FUkZRQWlNNFc2RkFWTnVmSXQwR2JjYlUzeEJ0UUcxQWJVZjJqOEE1YzMwaElYRDJySUFBQUFBRWxGVGtTdVFtQ0MA0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQAzOWNkZTc4YjYxZjM0NmI1OTMxNDVjZDFkMTZiMjFlZgDQBzRhdHRyaWQAMzljZGU3OGI2MWYzNDZiNTkzMTQ1Y2QxZDE2YjIxZWYg07LG+Lmmv9q8vMDWxvfR3dSxANAGKWltZ2lkADM5Y2RlNzhiNjFmMzQ2YjU5MzE0NWNkMWQxNmIyMWVmXzEyMV8xMjEAEAD/BwAACwAAANAFB25hbWUA1dSxvsm9ANAENGltZwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTk1NDM3NzA0OCw2MzI2NTQ5NTMmZm09NTgA0AddcGFyYW1zAHdkPSVFOCVCNSVCNSVFNiU5QyVBQyVFNSVCMSVCMSZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDM4ANAEB3RpcADV1LG+yb0A0AURYXR0cgC0+rHt1/fGt8/ntOWwrsfpANAJBGF0dHJ0eXBlAFRBRwBQCFwGAABhdHRycGljAGRhdGE6aW1hZ2UvanBlZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVvQUFBQW9DQVlBQUFCWjdHd2dBQUFFZVVsRVFWUjQydTJaUFphak9oQ0Z2M2xuY2l2ckVHV0VEclVEdEFQWWdmWTBXa0hqRmJTOGdsWklTTlFpZE5SaUJVeGdiR00zTlBhMGZkNzhVQ0ZJQlhWVmRWVzYrdFoxWGNkaXMvYmZBc0VDMUFMVUF0UUMxQUxVUDJQZmJ4b2RQYVVEWFNnRUVWOTZuZ29Ocm1TbkNwVDRiR3FKUTFOOE5pZzR5cDJpVU9LSzhRRm50elNUemhJeW81R1RuN0o0a1gvK1A3OEtWS3dEU00ybGE2a2tmbE5DM29NVkhIWTdGc0lHVzEyRWt4bDBIMDJvSTFJSklMTC8xRXdRcXpWNW9mZzRhcitJbndGTVppamthWUdzRnhPK2JnWXE0Q3VCTWlPdWhLTElvZlFCcFNWSWpURTNabFQwK0NqUkFnaWVxbTFoWTZtdUJ1ZWFFQng3ak13eDA2SXYyUVE1Ni9ONm9FSk5zeEtvRXpvOGlVanRTclpOZTN4YStweENnUzgzVk8xTVJnMkNqbldnRlFwQndHMmJmYVp4S3NWUmF5czJ0cG91dlE4ZzdiTjhhKzNnRjNKTU1RLzd0K3VPTUQwZnJOWmtNckFkSXBCa0dDMnZvTGZQTXFyM24yVGt3cC9HaFJtZ2Z0a0N6bnBFUHVEVjZDbjlFOFZFTE4rdjQzQlBUQkpXRVlRcU1Hb1l2QmdseWxHS0d1RW9lbkJZcjQvK2k3T2tPWitUWkFZdFBPV21vcjNrT2k2NWNjVjZDQWF4ei9TRXpCUm5SQjk4aFVqTjEwb3ZJdEVLbkx1Z3BsU0NqM0FCbHRRR2M1Rk4va21CMzZFT3BYYmdCaTJKZm9kS3dma3h2aDdabWVKNUpnZG5xVWN5UExpUzNYREhQb0xibkpYZmtRYmtGemxLS2dWeEpBcnhoR2hxQW5KK0c1WUNxTEg5RHc2NVFVejV2NmNKUldIVU5NSGZqY3pISVNSTnRuamZiK3ZEUHF0ZlFWWXJSQ29PcVliSkhIWWJrZWwxdkhOWmVxdDFUcEhlQTdsaEdVNzNXM2NDQ3FUT3FPMEc5MlRRUkZxUkVwMWxFOWZreG9BdjhVZmUybk9HTVJGZldtdzd2eGxNbGw2elpWZzl5UUc4cytjcjFtcWFQNVBNWU9SMWNYNy8rc3BJdE1sdzFtS0JKTk5JZWVLb0VGdWF5a0ptTVByVVdxakNvTDd5MlZzNGFzaFBTWWE1RnAzYjI0UEZsa1B4QXRRQzFBTFVBdFFDMUp5cVVlNVBPS1BOM3RTN3NRT3N4VnFMdFlNNXdXRmRHUEhyQ1ArN3d2a29peDhQdWVkS3BVSFBkdGlEUnhjeXlqM1VoNGYwVVIvVmc0VDFPbEpWN1ZqcmZkU2tnck5zNlJ2RzZDazNFV1UwTW5yS1RVQU9sWURnc0Q2U1NJMCthU1ZIZVZyZU9hWUhOcHdqbXM5RmlhRG5wT094aHR5Z2RpVXVRSXNnSVJKcGFkdnA4VnIrenFVWGRzUVZSRmZ1QVlrT1c2ZVQ1N3BoaVlTSnk0cmhVVVVJUVV1S1B2UDN1SXg2RUZBUlg0TVVMWkdFeW5uU1FwUFZGaGMrcm5Db0c5cW1PUmYxbWhHOXZNL1VGQkFDbW5qSTNJdmJtT0ZwK1NzYSs5QzZCOWo3NjNQMy9QcmV2YjA4ZDYvdlhmZjI4cU43ZWV1NnJudnJYbjY4ZEcvZGUvZjZ2SDkzYWFleE0vYjIwdjNvQjQ3UE9YenJQdmFRaklwUm9MUUFkMUk4NVZGcGtFQThLWTlubTErNTN3U2F2Ukp4Qzk4MDI3RTVDZW52WEhwUzY3NUlidDBwRTdKYzRvK1hySVB0WDJTZmt2SkhFQVBPMW45VEg3VUhJc2djMDE5NFN1MHByZTM3cWhYcjNHQm1TT2FQektqcHZySmtjK2lsVm10eWNSTHhVbDlpYlh1V0lZVThOS01EWXA5UVJCK2RVWCt1Y0JkTzdVWndsanJ0Z1JyMlpGZmVPZjdkUUMzcXdRTFVBdFMvWUQ4QkxyYU9iRDdLTXU0QUFBQUFTVVZPUks1Q1lJST0A0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQA1MjIyMzVhMTgyMjI0MTg4YmRjYzBhYjdkMmRiOGNiYQDQBzJhdHRyaWQANTIyMjM1YTE4MjIyNDE4OGJkY2MwYWI3ZDJkYjhjYmEgtPqx7df3xrfP57TlsK7H6QDQBilpbWdpZAA1MjIyMzVhMTgyMjI0MTg4YmRjYzBhYjdkMmRiOGNiYV8xMjFfMTIxABAAPQgAAAsAAADQBQduYW1lALPCzrD2qgDQBDZpbWcAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0yNTg0NDAwNDIxLDEzNjY3NjEzMjQmZm09NTgA0AddcGFyYW1zAHdkPSVFOSU5OSU4OCVFNCVCQyU5RiVFOSU5QyU4NiZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDM4ANAEB3RpcACzws6w9qoA0AURYXR0cgC0+rHt1/fGt8G1yMvQ9dPvANAJBGF0dHJ0eXBlAFRBRwBQCJgGAABhdHRycGljAGRhdGE6aW1hZ2UvanBlZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVvQUFBQW9DQVlBQUFCWjdHd2dBQUFFcDBsRVFWUjQydTJaTzVMeU9CU0Z2My9xejFGR2FHV0VoQW9tdDNaZzcwQjdRaXZBWGdFbW55b1VPaVJxRVJLMXZBSlBZQjQyRmpROVRmZlUxUGhXVWJ5czE5RzV4MWZIdjlxMmJabml3L2hqZ21BQ2FnSnFBbW9DYWdMcWZ4Ty9QM1YxY0JRVjZGd2hDTGpDTWM4MVZBVkhsYVBFbzZZRkZacjgwVVcrb2pncWNpV2V1TjVUMlMySHU1MGxwRVlqNDdQQkZTVkJHYlQ4QnFEQzNvUFUzRTVkS29rckM4aE9ZUGtLdTQwdG9jVFdOOHRKcjVQMSs0QlVBZ2gwUTRuSEU1b3R5WEtGaUFMaEhqUVVLSlZnblNQSVdQc3ZBZVZ4dFVDWlNMZENrV2RRT0kvU0VxVEdtRTh5S2poY2tHZ0JlRWZkTkZCYTZxZkJlY3ptc200aS94d294enVIaWREc2VhRDhuc05Nb0hxN01oZUJmVld3UFZ3blViaU1YSUVyU3NaenUyRlViOUZoNzJtRVF1Q3B0b2VPYVZ4VE1ScE5QVjVvUC9VdSs1aGoxSkJ0ODF3akI1OWZ3cWh1OHN6RWVIZVNGR1BHdzZqYzlFRDlpRkVlVnplUVFIQ09zTXpJSmVBZnpVbWliMm43MFJyc0Z0SnN6TWJnS0VxUHpPN3I3Ty9ucU9zSVNjSXNESGVuVzd5SWFMSWxLbEVSalNKSnlZU0Q1ZkxTZno0Z3piQk5raHEwY0JSbFRYT3JkZHhxNDR4bGxyUFlGNVMxSURXbVk1R0xTSWRaNEFwTEliUG9aajRIRkJLdG9LcHUrbDlJY0FGdXdKTGFZRzdZNU9ZSzNCRjFUalZYVUhwSnBpWEJIVkVMcUZ4TXJ5TVREME10OFpWbEg5RVlYeFVjUjZuM1FPQnZzdURUUUVtbElFUldJZWFJd3g2UHZKdmp2ckk0a1pGTEFleXgxbDRBTUxrNGJlaWQvbDhXQVZkVW9IVzMyMXF4dHdYSExFZmwrZ3JxZ3hMbml3V25aSkVjY0M1Y2M3MXdoUE5uYTNGaGhwaUxNOVV3YVFMTWtJdm43bHROWFdLdHZieUs4MWlmQ2Urb2hlcUJJTkdtcS85Y09ERnljZjMrOVlJekJwVk8yZHVTYW03UUJCcXhJRlNXTWl6SmpBRlg0QzY2MVdtR01RRlhXR3h6LzNiOFllb2R0cHpJMldYYzRuekg3LzgrWTZrQ3poMUlWTWVjdVlEakpkWHlqbTBoWVNFRlVzaHJpZk5xb0xyZFNhbXN4UUpKcXBIeXFsRStOQnhxQzZuQjZPZjA0S2w0V3FPNnNTNGpDOWplMW1kSjJzMVhLSElkSCs3WDVIQk9oK0lKcUFtb0NhZ0pxTW00ZTNuNENydGZQS2laenRWenJ6cU8rRnFYczk3SlFPU3VoVEwydTc0U1AxWWVQSElQb243UmJFbW1BbFhQWnVuT2pIbTM4SUhiZXZydTV1U3ZRT1hmWkZRSURmZmNOcUZ5MG5BOWEzV2dMaEE4T1A4SlJWZFlENTJFUWJYK0lqYjlJRkNCWTRDR3NkTncvbDhvemJIcUgyc0UrSmpORWk2bVlIZThVZVJHalE2MTRYUjBlbFg4VE9xZGpERm1BalZ5RTY4THZ6aWV2c0p1QTh1bHdCTlB2WE1xYTZxSEd2VlByT05vdEQ4UTc3dDF1OTY5WDk3dngxdTdXYTNhMWVhdDM3aGRyMVp0LzZkK256OFZQNUI2SGxlRHpBUkNLSVIxZUJYeHFQdGEwM2NBWnAwTElUNjRVVVJaOVNvMi9RU2ozamFyd2M2Lzc5WkR4b3pwMTI1dW1QSzJXWTNhbkJuMXR0bTB1OTE2eExqMmZkZXUxN3YyL2IvQXFPQUt0bUZKMW5zK0o1Um1XWlNucHpWaXJGTUExR052blMzV2RuN1d1VmxUbDdobGhxYkNmWE5lZkp1WWQwYmR2YWUxSjJERTBMVHpsZTJBelJYaVVoZlJQUkZPeHRmdUYrWWk3TitkZXQ4QzFHREJUMXozcDZqNTZ6Qitrakp3TjA5VmVxdzJHaFNpZmMzckY2VC9sY3A4T2hSUFFFMHhBVFVCOVgzeE53MzN5NzJRRFU3QUFBQUFBRWxGVGtTdVFtQ0MA0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQBlOWNmYjIzNjM3MjA0ZTQzOGNiMDE3MDAxOTY0ZGI1MgDQBzJhdHRyaWQAZTljZmIyMzYzNzIwNGU0MzhjYjAxNzAwMTk2NGRiNTIgtPqx7df3xrfBtcjL0PXT7wDQBilpbWdpZABlOWNmYjIzNjM3MjA0ZTQzOGNiMDE3MDAxOTY0ZGI1Ml8xMjFfMTIxABAADQgAAAsAAADQBQduYW1lALjf1LLUsgDQBDZpbWcAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0yNDg0NjE2NzE5LDExODkyNTEwNjkmZm09NTgA0AddcGFyYW1zAHdkPSVFOSVBQiU5OCVFNSU5QyU4NiVFNSU5QyU4NiZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDM4ANAEB3RpcAC439Sy1LIA0AUTYXR0cgDV1NPWzaLWrsbeufrD8cWuyfEA0AkEYXR0cnR5cGUAVEFHAFAIZAYAAGF0dHJwaWMAZGF0YTppbWFnZS9qcGVnO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRW9BQUFBb0NBWUFBQUJaN0d3Z0FBQUVma2xFUVZSNDJ1MlpPNWFyT0JSRmQvWHEzTW9jUWtaSXFLQnptQUhNZ0RtVlJtQThnaEo1cjJXRmhFUWx3b29zajRBT2JHenp4Mi8xKzNRL2JnaVNrSTd1dVovRFc5TTBEWnN0Mmg4YkJCdFFHMUFiVUJ0UUcxQy9qZjM1Mm5DTFZoVkJGdVBqTUxsaG44YjR0N2ZPNUdoaVV1blFxcUNlWGNzanlxNXpyVllVN2VCZFNKSkt4T0M3QlRVN3dpUkZpcmw5clR5Snp2bVNZMnVOMjl1Nk9zcU9ITndqU2dURzdFbGpmMlN6UXlEdjVneTVocmdIaU5VS0l4TFN2VUVWOVNpb2t6YXhabnVCeC9LeUNoQXZ5b2o5YndacSt1YXNWbFJCUm94R1ZRSFowMWVjeVRIN2RQRGhoK2VKN21HYzdNeWZYc091OEZqQWl3YnJUWG5VMUY2L2tYcEQ4MldJMFJxTkkreDlSZXdGZFdYQmYzN3VxT3dGOGV6enpxQkxRWlN0Slk1UG5HVnp2RUlWamxENk44OCtNdXBRdGFMc1BGQ29DWEJYZWRTVTYrN0NoRlNLU1c4WXBkOElSYnJyZTBSWlFEWHFNU3NvMklLVXpNZWZWejNxN2RWZTcwNDFmMldndGMrVXZONnVrOW5FaGl3Ni8wTDJRSnc3UUg5dlJUMEc1b3hYclloUEFEU3I3TnljRGgvTlo5TTBueC92emNmbjA1dlRvVG1jemszeitkRzhQNy9vekwzT09aOE9vMlBPcDhOMXpmT3BPZlRlMzkvTjJtZno4ZjQrOGYyeHNZZm1kRzVlc3BVeHl1RXVzRytwWFNnVTRIa2V0Zk5KVWdGSVFxTXh6dTk1bFVDbUVWb3BqbmlqY1VnRVBzNVluTENJUUw1WXNXaFVVZU5GR2VNaGJ0eWI2bU0vUHMyVkoydXA1d3o1c1lRd1FicmpqWG9UOGVkZUx2U282WVdFcnNUNlNTZmJqZEdHNTdwcUlpNjJBRTBkYkNyV2ptWmI2eSt1c1RxWWF5UytMU2d2QzF4ZUtCTGJ3SDAvY0FjbzFoM2NhbFFCWWVnb3k4dksvWUJ6RGlyZFRVd3JnVjRGbE5VYTRwRXFlalFpL2tYby9xYTh6R2VvZTZieklpS0tSNEpvUFdXbU5vcW83dnRwdmYweVYwc0ZWVy9OcDh2cnpOOU5ac3UzVGVIY211SU5xQTJvRGFnTnFFMjRXMWV3TDZUbWtYUzhXRjdNMURaM3ZXcW0yNTJUZHRiMmpOOUZabGt1MkJ3bTErdWJ6NXU2TUZiQVZ2VU9mMEdTRkRKRzVCcnJyMWM3Znd4UUN3cmlMb3orblEzYml0cVR4R0x1UXA1Nk9xV0pJaWc2N252dFVSY3Y2M3NCSldSS0pxZjZLWWV4dllhMGVHeDR5a3ZIbTlrYU5UblJJOG95c2lkcHg2ZnFhR1l0OWF4V1ZEL0RvNFp0eHhGVnRqZVhER2padjgwcG9WK21HZkxlTnc1L0hvekhIWWN4TjdYVlZiOFc5ZkJqV21YMjZsRStvblNQdnpWbXdTTUZWQTZtQXAwekJoY094YmpLZ2dqNll6WGw1Y0t1Y3NnOVhNckhwWFdvRi93TW9BWVdFR2NPblJ0RU90elJPUFY2eis3YXRjV1VBcG4xVUxTR1VrZzZqKzFOR2RpRitNNWc5L3hhMUt1MG91eWsvTWN0MWhyQ1JjbDFLQUUvWEVRZ0U0RldpcUxWekowaEx4aUlnTGFDS0FreEdnSXBxSXhqbFZEMW80QUs0amFXVEdVanU4UmRBbEdnVFhCTkFzOENvQkFJSkdrbWI3RktVZHpBOWdjUklBWm5NTmNNZ3d3MFpmR3JVTzlTY2xUbGNzRTVtc29maGFndlE4enhpTjVueUs5KzhIbGt3RjJZa0VtQjFRcFZNUHZ2cmg4Ny8wTUZwK1BMUVYxb1JKSjE0NHVRcEFua3gxWmJCNU9yVzNtd0kreU45K09uVWtBVkw5ZEZyOW9tM0cxTjhRYlVCdFFHMVAvQS9nRk5LK3c5RDluZ05BQUFBQUJKUlU1RXJrSmdnZz09ANAOAmF0dHJwaWNpc2xpbmsAMADQBCF1cmkAMTU4N2Y0NWNlNjk3NDAzYWE5Njg4Zjc0ZTQ2MjU1MWUA0Ac0YXR0cmlkADE1ODdmNDVjZTY5NzQwM2FhOTY4OGY3NGU0NjI1NTFlINXU09bNotauxt65+sPxxa7J8QDQBilpbWdpZAAxNTg3ZjQ1Y2U2OTc0MDNhYTk2ODhmNzRlNDYyNTUxZV8xMjFfMTIxABAApQkAAAsAAADQBQduYW1lANCh0KHWvgDQBDZpbWcAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0zODI1MjQ3NTQyLDM3MzMwODk3OTkmZm09NTgA0AddcGFyYW1zAHdkPSVFNSVCMCU4RiVFNSVCMCU4RiVFNSVCRiU5NyZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDM4ANAEB3RpcADQodCh1r4A0AUVYXR0cgDRx9be0KHQ/bfnwdbWvtOx1q7X0wDQCQRhdHRydHlwZQBUQUcAUAj4BwAAYXR0cnBpYwBkYXRhOmltYWdlL2pwZWc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFb0FBQUFvQ0FZQUFBQlo3R3dnQUFBRnIwbEVRVlI0MnUyWlA3S3JPaExHZjNmcTVTaHpOaWdqSkZUd2N2UldZSGJBbmc0ck1GNkI1UTA4S3lRa3Nwak0wV2xYVGM0RStCODIyRDYzenAyNlZROUZMcEJwOWFmdTFxZXZmM1JkMXpHUGwrTmZNd1F6VUROUU0xQXpVRE5RLzVqeHgxdXpncVBjdG05TmpiTUNpNlBjUWxaWTlPbi8xY0dRRzNYMzJaSW1LYkI2d3FaWExIT0RHak1rbnNxQnZid1hmUDhBbzhZK1YvTFVoU2lkdGdYUWZYbnN1ODNIcHR0M1hkZDFuOTF1ZGY1OU56NTMzZW84YjcvcFZydlAwK1BWNWZkKzg5RnQ5bE5tTnQzSGF0ZDlQbDNLelp4YmU2TlRWOTN1ODRsUEwyeTlGMUVFWE5tUW5DTmtNdkJ1SWtRWjh1TFhwTUV3T2xyV3BaQ213cEVqMjdJY2paU0xIOVVCYzRtY3MxL0pONlVlbWlUZTBnVFFlaHJNcG8xSmJPK0lWMHR5b3dpdTRxRFVLVlVTckRxbEloYnprRTBWRG51WG9vS3Yxb2k1cHFpMkJka2diUU91OUtUTFlqVHQrcS8wZmhqdFdic0ZoZFdJOTBocTBRak45d0FGT29uWk5vSEprQW9OYlp4Z0FXd0Jyc1NGREZwRmtrQkFvY0lCVVlEV3FOQndVRU9nZmEwd3hiMm5DbU5UcXJValRFVzBIQkNPdE91UytxSDBMQWZBSzJOSnF6WE9wOGpGbm56anFhY1Q0clloVE9MVUVpZFhON1F0c1BUZzlVOFRFaFZvQkdDQlFnYkw2M2ZYakFPaERDWnUyYnFoOVhaYlVwWWxwVitRRndWRlVWQXNVNklvWlZrc1NhTUluWXdETDNXTnlwNlhrcCtrQndvVkNRZDVrblo2V0VjY3RnL3gwNS8wNVVSU21OeVMzSnhnTG1pc1VkUDdaRFBpZHNzdFZuRjJBdWFVdHBXWElTRDUyZDdkdWtVNEFtMFRmZ1dQVWlRYVFuTjRlSE40aUFiaElCRktuZGQxUkMybVFRZytvTzJUby9sY1g5S0kxbnZrOXZzaW5BMWRiQnhyMW1VZmJWZGdGZjNyZ050Q1ZpeEpaUWo4dDlTb1BnTnljZ0t1SG9iVnd1UjNoVmtRZEwrYjR2RnRqTEZQSUxENVd5bWdURTVoZW1mbHFFaHV5b3ZJc1U5bU5jS0pwQ0dnU0JCOHRZV3NRQU02ejNDbEl4UUpIQVVSanh0d3MxL056T1dBcUw0T2VWZkRWTzM1YVg1d3JYMXlrSDR6SkVhRk5XN2srSkltY0ZRTFZQQUV2YndodUJxYmdmZGN5NHBhakViMmo5ZkNYWDg4MThjM25ZaFMvdEtCdjdIa0MwL1pKQlJXditaZEYxNnpwWjA0c2JobDRGcFIxeTBRRVVWSGxDbXdlbVN0VWNxZkt2QmZrMlBVNjl0SG5JM2ZGSDdNQ3VkOEtaNkJtb0dhZ1pxQm1vVzdjWm93SW94TmlISmp4Ky8wdkt2OGdhOVlCODNTQ09zeHBXMVVZSHN0QTRtdldML2lPSEUyU1dYKytHMjI3Rml6TG11aWRNbFNPenc1UlRHbUlZMWZiK3p5UUZWNTFNUzhLNnVmNElta0xPMDBMWDZMUnozSXFGRktxbXJxMFExZlltVE5tOHJ4YVJjWmdDRyt3aS95bnZpTlJ1S1FtUDVNaEZ5akROTGxDekw2TmNMWmkyUHE3cVBCbFd6bGhkNzhNdlh1R1hWTVZpUTBJMkJNTWVkSGxpM1BBWGkzWkh3NTlVSkR5NUYyN1ZpY2E0RjRHb21JRUJxQk4yMk9LaE1tTCs0dTFvSG1yaDZKci9COEEwaS9zcGlIUm9paUNHMFV2dktvUEtGeFFtSVUvcUFZSWpWMVAyd3A2NUhDUE5MbGliUHM1bHVlUlc1UmI1V0ltS3pJQjVMUDlGMzFiajJUaHdYdmRtSDIzV2F6NjNhcnZwUHh1VnQxcTlXcG0zTHFzT3czMHgyUVllZm1lVmRsZFdtVm5Ec2oxMDdQNTI0MTBiWFpkNXVQais1anMvOUNNK25XMXV2eFZrU0o5NUJZOEwzS3BSSU5nVjZSUEFsZjJpZ3FGOUJXMzFBSkM2NlBCcHMxbEM1Y2krdE5qYmp2cXBRMUVNZkV2SkU3TjdmKzRsdTFuSjhnbklMRzZKdFFkdko0WEtzRWZWWU1wU0dnR2NqVjJwTFJ2ei9MeEVZY1hucDkvU3pwWGlSZW0xeEZ3T01FUUdYWk4wbUxOd3I4L3dNb2JXNUI2ZlZ1UFZhUWJZcDR6MythQURwNWlBZHRlODNvTE9OcW93bk9JK0twMW9MSllxSTBRM2xIUVBkS1kyaG9hZkZlVU9aS0djb3RwR2tFeC9vYzZMOExNMzlMcXlYUEFRei9Qc3ZFcW4xc1NzWVpmVmVxbng5Y2hWN21hSEY0Rk1hZTBqaHBUcTM1dnYxVlZuMmhsZWJhcmplSnAxcVhsRzl4cVdGaGp6UDd2bS9kN3pUdVd1OFBMZlg5NW1zRit4dkhySERPNnNFTTFBelU3enorQnlpM04wNFBDNjNCQUFBQUFFbEZUa1N1UW1DQwDQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpAGE1OGY4MTc1ZTRhMDRkMmE4NDEyMzU3NjA0MWQ4YTQ2ANAHNmF0dHJpZABhNThmODE3NWU0YTA0ZDJhODQxMjM1NzYwNDFkOGE0NiDRx9be0KHQ/bfnwdbWvtOx1q7X0wDQBilpbWdpZABhNThmODE3NWU0YTA0ZDJhODQxMjM1NzYwNDFkOGE0Nl8xMjFfMTIxABAAHwEAAAYAAADQBQduYW1lAMvV09DF8wDQBDZpbWcAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0zMjc0MDMwMTczLDE1MTA5NDc0MTImZm09NTgA0AddcGFyYW1zAHdkPSVFOCU4QiU4RiVFNiU5QyU4OSVFNiU5QyU4QiZyc3ZfY3E9JUU1JTg4JTk4JUU1JUJFJUI3JUU1JThEJThFJnJzdl9kbD0wX3JpZ2h0X3JlY29tXzIxMDM4ANAEB3RpcADL1dPQxfMA0AQhdXJpAGUwOGY5ZDI4ZGJlYTRiY2E5OTJmZGUwNDQzZmMxYzYwANAGKWltZ2lkAGUwOGY5ZDI4ZGJlYTRiY2E5OTJmZGUwNDQzZmMxYzYwXzEyMV8xMjEAEAAfAQAABgAAANAFB25hbWUAtsXeyLriANAENmltZwBodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTQxNzk2MzY2MTcsMzg0MjAxNjYxNyZmbT01OADQB11wYXJhbXMAd2Q9JUU2JTlEJTlDJUU1JUE1JTk1JUU4JUExJUExJnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMzgA0AQHdGlwALbF3si64gDQBCF1cmkAZTFlYTY4OTIxYjc0NGRhMjk5MWE0YzI1YzI5NTk3OTYA0AYpaW1naWQAZTFlYTY4OTIxYjc0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EAAOAAAAAQAAANAFAnNob3cAMQAUF3RvcF9jYXJkX3BybSNudW0jYmFpZHUAAQAAABAAmDQAAAwAAAAgBagGAAB1bml0ABAAAAAQAGwAAAAEAAAA0AUPbmFtZQC0us3tutrJq8j9t9bW0wDQBCF1cmkAYThlNjg0MjJkNmQ5NGE2MGFmYmI3NjhiN2Q1Y2Y5YTkA0AUIcGF0aABsaXN0WzBdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDE4MAAQAGQAAAAEAAAA0AUHbmFtZQDW7MD22bsA0AQhdXJpAGE1YjZhYTIxZjAwMzQ5OTQ4M2Q5NGI1MDE5MTA3ZTU2ANAFCHBhdGgAbGlzdFsxXQDQCQ11cmlfZHJzdgBzY29yZT0wLjAxNzEAEABkAAAABAAAANAFB25hbWUAs8Lc9sGrANAEIXVyaQA1ODk1MjIwZWZkZWE0N2FiYTE4YzRiMTFkMjk4YzE4YwDQBQhwYXRoAGxpc3RbMl0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMTcwABAAYgAAAAQAAADQBQVuYW1lANT4va0A0AQhdXJpAGEwM2NiZjE2MGRiNjRhOGNhMmQ4OWI4MzA3N2NiYmRkANAFCHBhdGgAbGlzdFszXQDQCQ11cmlfZHJzdgBzY29yZT0wLjAxNjkAEABiAAAABAAAANAFBW5hbWUAu8ayswDQBCF1cmkAZTY1OThkYzc3NTA4NDQyOGEyZGYwNTAxNjZiMTg1ZDQA0AUIcGF0aABsaXN0WzRdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDAwMAAQAGIAAAAEAAAA0AUFbmFtZQDB9ezHANAEIXVyaQBjZjgwMjg3ZDg1NzI0ZWQwYjliY2YyNTkzN2JlZjJiMwDQBQhwYXRoAGxpc3RbNV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMDAwABAAZAAAAAQAAADQBQduYW1lANbc0Mez2wDQBCF1cmkAY2QwZjU3ZjlkNjJkNDFhMmJhNmI3YjZjNzc0YzljZTgA0AUIcGF0aABsaXN0WzZdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDAwMAAQAGIAAAAEAAAA0AUFbmFtZQCzycH6ANAEIXVyaQAxNWY4ZjYzOWU2MTE0YzdhYjIwMDI2ZDk4OGU5N2U2NQDQBQhwYXRoAGxpc3RbN10A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMDAwABAAZAAAAAQAAADQBQduYW1lAMHWx+DPvADQBCF1cmkANGM1MGI2MDczMDEwNDRkN2E0NDE3NTU1YmZkMTZkOWIA0AUIcGF0aABsaXN0WzhdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDAwMAAQAGQAAAAEAAAA0AUHbmFtZQDDt9Het7wA0AQhdXJpAGEyNWZhMWQ2ZWNjZjRmZjJhNjRmOTU4Mzk3YjZmMDg0ANAFCHBhdGgAbGlzdFs5XQDQCQ11cmlfZHJzdgBzY29yZT0wLjAwMDAAEABlAAAABAAAANAFB25hbWUAz/K7qse/ANAEIXVyaQA1MmQ2NGNmMjRhYmI0NTYwOGJhZGE3NmMzYTQyY2E1NwDQBQlwYXRoAGxpc3RbMTBdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDAwMAAQAGUAAAAEAAAA0AUHbmFtZQDVxbn6yNkA0AQhdXJpAGM1MWY2OGJiZjdiNjQ1N2I4ZDUwMjNlZThhODRhNmZhANAFCXBhdGgAbGlzdFsxMV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMDAwABAAZQAAAAQAAADQBQduYW1lALnY1q7B1QDQBCF1cmkANDBiNzAzY2NlNGYxNGI5ZDk3ZDE2MzZlMTg4OTQ5NmIA0AUJcGF0aABsaXN0WzEyXQDQCQ11cmlfZHJzdgBzY29yZT0wLjAwMDAAEABlAAAABAAAANAFB25hbWUAwbqzr86wANAEIXVyaQA2NTNmYmU1YTdlOTM0ODlkYjU2OTg0YzQzNzU0YjI3NwDQBQlwYXRoAGxpc3RbMTNdANAJDXVyaV9kcnN2AHNjb3JlPTAuMDAwMAAQAGUAAAAEAAAA0AUHbmFtZQDN9dfmz80A0AQhdXJpADA1NjAzMmRlZTIwNDRmNTdiNTIwNzk2MzNkYzFjY2Q5ANAFCXBhdGgAbGlzdFsxNF0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMDAwABAAYwAAAAQAAADQBQVuYW1lAMD71scA0AQhdXJpAGJlMGI0ZDY2NWQ2YTQzMTE4M2NiY2E2YWRjN2VmYWExANAFCXBhdGgAbGlzdFsxNV0A0AkNdXJpX2Ryc3YAc2NvcmU9MC4wMDAwABQPdW5pdCNudW0jYmFpZHUAEAAAANAJBmNhcmR0eXBlAHJlY29tANAHIWNhcmRpZAAzODIwYzE3YzU1MWYxZmM1MmU0MjJiZTEzNjc0MzdhNQDQCQtzdWJ0aXRsZQDG5Mv7yMu7ucvRANAEQnVybABodHRwOi8vd3d3LmJhaWR1LmNvbS9zP3dkPSVFNSU4OCU5OCVFNSVCRSVCNyVFNSU4RCU4RSZzcmNpZD0yMTAzOADQCAJzaG93cm93ADEA0AkCc2hvd251bXMANAAgBawsAABsaXN0ABAAAAAQAKcIAAALAAAA0AUPbmFtZQC0us3tutrJq8j9t9bW0wDQBDRpbWcAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT04OTIzOTEyODMsMTkyMzI0MjI1JmZtPTU4ANAHgXBhcmFtcwB3ZD0lRTYlOTglQTUlRTYlOTklOUElRTklQkIlOTElRTglODklQjIlRTQlQjglODklRTUlODglODYlRTklOTIlOUYmcnN2X2NxPSVFNSU4OCU5OCVFNSVCRSVCNyVFNSU4RCU4RSZyc3ZfZGw9MF9yaWdodF9yZWNvbV8yMTAzOADQBA90aXAAtLrN7brayavI/bfW1tMA0AUTYXR0cgDR68rTtLrN7bXE0ru087DcscoA0AkEYXR0cnR5cGUAVEFHAFAIzAYAAGF0dHJwaWMAZGF0YTppbWFnZS9qcGVnO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBRW9BQUFBb0NBWUFBQUJaN0d3Z0FBQUV6RWxFUVZSNDJ1MlpQWnFqT0JDRzM5bG5jNVE1TkJraG9XNkFiZ0EzMEoyYUU3UjhnaFluR0lXRVJDTkNvaFluOEFaZ2cyMU1lN3A3ZW1aM3FjZ0dJYW8rMWUvSHQrUHhlR1NUTitXdkRZSU5xQTJvRGFnTnFBMm8vNDM4L2Q0SGd6TzRYWUdLSDdudnNXVkZlNzBvU3NrTGlWamVBT04yRlBkZThOTTZCWnl4b0Fxa1dMdjJ5VUM5SlVKS01JNFFqMERjZ09LeHBwdCtMd0VKbE9YODM1NU1LK0xnTUllYS91cWFyWHQ2U2s2UDdETTlnUllhdkpBVWMwQ1dybjBZS0c4cHEydFRKcVVnSXMwTHBBZzRjNkFlcktBMWtCZTcyVGFHVGw2ZllJelNldjR5ck9tUTk3eHRRQUd0d0piTnNONkMwaG94ZXRZaHlBbWttZTREOElPdVNlUHAyM3AyR0NjYlB1aFJVWnBUakx0Y3U3bTNoc0UvQkxMUXlMUENPOFJqY1RQemtoSGtzcjdDUmkrRVZVdFZ0Z3ZySzhweU5QeEM5ekhjOERnZmsrdnBNQ1lidmpEMDhKWkRMY2gwRFBoSFlwVkN5OUVReDY1UXJHYW50aG85WVUrV1FkVWthQlZmSE9DYTRjRTVrTVZqaC9qTGdBb09NN3A2WlQxYXZTT3NMNVBUcFZlSjY5Q2J2VHFBU0c2ZjYrc0RrOE5GcEtvZ2FReVcrd1hwcDRIeXRtU3dvK1V5R3VZNUNtaEw2bjFHaGlmT1VueXpvMGdhakJQanlYbWF0cWNOam1TV3Q0Z1ZXays1UlY5cDdxMEZOZk93c09aaG94NG5RT1IxMmppRkhnaFprTmdTaTM0VHJJZUFpcFZHWDZxT05ZNGc1SjN5SFJNSE53UmNyQ2hpai9VZCtJWTJpb2p1SEVRVVJkQlh5ODUwdXJqUDBQSkdRVTYxWU5ocnJJUnJ3SjRmemVtTXhjZnFzME12NEV3RlVsTmdNVTZjRS95S09xZ0NiRm16enpKdzNYaHRNRVdjRHNKYnltYkpvMHFhWkY3cXU0c2NsY3hDdUNJbGpjSk1WOGRPcmlaSFpLR0d0ZUdUZ0JwT0t5TE54enlCUW5XR3N1UnVXWjFYTk5LY0lnNVl0OUlHdE1zZXRVK1cyb1A0b3RrY2lrZENaOXdacUlBZ0lkem1xQVVIQ0wwZ0VaK1FvL2FadmtuTVFoWm9HWENtcE94dkRSZ1NOV1JhbjBOQlVIRTRhYjNQVUNzQW5EM3F1a0txdVljZnFFV0cxdU56b3FVYTBZN1NISUZiekZFM2plNjFMalA1dGpHYzIxQzhBYlVCdFFHMUFiVVJkMThscTJUYndndzRNQWdlV3pZa2VtRndEZzV6Q01pTGV4NWJPa1QrTmtIM3h3TDFwc3o2cXVBTURzQTNoRlF1c2d2ZURWUk5kZTVhSTlKVTBOTFRIazR6NEhLLzl1OEdhZ1RJb3NabU1PQmNTOTlmRGVqN0RDMDdYRWpKOVE1Mzd2aUhCalBOTlR0WFVvVVYrdmxQQVdwaUlWaGhTbWZUL201aGFkZmcreG1KNXkybWt4UVNuR21RaFVJQVNuVllGMUE3aHhjQ3p0NVVZMTN5d0h6Nkc0RzZaU0VXQnQ1TGt1S1dUYWs5YWJvL0V3S2hDNGpkWUxRc0VteFpVcDFYMThNQlJDbTVWb2dQNlA0Qm9DNjU4VGRsOFl0TG9BdlFOaDdpOVh3aGRnSTYyR2NGVWpoc0V5QVdWMFRkQXZkZVZyUjlQYzJXM0tPVWZ4bFFFemYrL2xoMDFDSWp3K0ZDL0hoRkVyc2hvY3VFam5pYStCZDQ5OVZQWWo4aHYzRW9ucFZzMXIvaFRmVE9WTjY5TlhSSlRPZ1MxRjJFUjRLeDcrbFpwMm4rMEtvM2hBU1pIZzJYS0dFb0xRdktlNXFRa3V1RXhoamMrTEV5VGdSVjVVbHorVWF4MkpQcGd2aWpLaCsvV242OEhKK2VubzR2UDVadVBSMmZubDZPMDYzWDQvZm41K1AzMStuLzYrdHMzZXYzNC9PZHZjWWRqeThYKzUzZU05L3pNZm5TMFBQMmdUN21sR2YyR1JuVlZVVWNDb2lQODFsNW54RjNDNkcwNkdYdnlGc2JjYmNOeFJ0UUcxQWJVUDhCK1FlVTE3d2lwVkZDT3dBQUFBQkpSVTVFcmtKZ2dnPT0A0A4CYXR0cnBpY2lzbGluawAwANAEIXVyaQBhOGU2ODQyMmQ2ZDk0YTYwYWZiYjc2OGI3ZDVjZjlhOQDQBzRhdHRyaWQAYThlNjg0MjJkNmQ5NGE2MGFmYmI3NjhiN2Q1Y2Y5YTkg0evK07S6ze21xNK7tPOw3LHKANAGKWltZ2lkAGE4ZTY4NDIyZDZkOTRhNjBhZmJiNzY4YjdkNWNmOWE5XzEyMV8xMjEAEAB5CAAACwAAANAFB25hbWUA1uzA9tm7ANAENmltZwBodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTI3NDMyMzQ1OTksMjkxMDk1NTM2NSZmbT01OADQB11wYXJhbXMAd2Q9JUU2JTlDJUIxJUU0JUI4JUJEJUU1JTgwJUE5JnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMzgA0AQHdGlwANbswPbZuwDQBRVhdHRyADEyxOrOqsH1tcK7qrL6z8LSu8WuANAJBGF0dHJ0eXBlAFJFTABQCMwGAABhdHRycGljAGRhdGE6aW1hZ2UvanBlZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVvQUFBQW9DQVlBQUFCWjdHd2dBQUFFelVsRVFWUjQydTJaTzVicU9oQkZkNy9WT2NvSXJZelFvV1pnejhDYWdlYlVHZ0gyQ0s0OGdsWkk2T2lLa0FneEFyL0FmSXo1R2JyN3JYdmZjaVdBSmV0emRPcFVxWGhyMjdabHNvZjJ6d1RCQk5RRTFBVFVCTlFFMUFUVXQxbHdXQmRHZFkyKzdQV04rTklSdmpoK2NDVSszdXMvYnA3M3B6WmNyMGt5UXk3UGRrZFpyZGp0ZjU2M1I3eGZ3MjZOdGJlSFByd2psTVlFaDNWZ2NqRnVYVktSK2dvWFR2TkdYK0xJMFdvNFJzRFZrQlViU2xzZjF3eHd0c0FrdzV4dGNoUlFFVjlXckVoSVpseE83Q0EzQm5FRXpSRk1qZ1FJbmlBTHpISEIzZW1SYTlRdEhHU09rVjNmaDJ2cTc3UzJkRnROU05OYjc5U1FHYVFBYVZUdnVXZXU5MnQrblZFQ3BRMktpQy9YZytWTGN0MGJYaXlRTThjbWdoVGQ2U2tqbm1Mc2hWMVFjVVphNlAyYUx0MXNvM0lXVFhucFNzRVRsU0dYa1JpaGNRT2dlL05jZU0xVHJqZE9aWWc3d1VKQTlCNnluRTFwcVhlRGJwVmxOZHk0ekRGbTZOSVJaYzVQT3JpU3phSGRRYTVWeDJZQ1RaUjNtWm9Ed1ZYVXBLUWtaRWF4MlROODdrczJTalAzbHVaTEdqV0tGRFV4TGJxTktVMU94UHVFN0xqWkVhNTN3S2tKN0JJMWNJZkk1a0Jwb2RES1lVdFBvUlVpTkVUWmdSYnZzTGFPS1lWZTBKUVZ0VjBmRHc2QTlkNTVGejhJVkhDV21xeW5SMTlqWmhOMkpFb1NuTVdMb2lmTWdyazRzYVRZbEZSbEpDRWk3d1dBZzJzbkM4UlJUc2JiKzdlQ2RIVHNnZGdPZGViTTlZQloyckhpNkhXT0ZTbUZCQ0VOd3BkWXB6QTV4QjNNK3dxcU5GbnN3THlMVXhOSnM1VFFkRkd4V3UzdWhlRlhvdDdqaUhnZTJmb0I0RnIvQjY0WFBXNEZhWEVDVGlpTjJiZkZtVUFNSW0remh0MjZ3czB2UmZna1VSb1pQUUVRY3dHSjZzRFlwemNpNjRUZWw1NzVsVUhHcHdlNzh6Q2NaSVljM3oxZlZkalZRSnpGUzlURTF2SG0rN0VKN001VTZ4VHlqZkNVVllrdk5FcHA5TTFKTm5nUG1aYjdLS25SUnZVT1VkR1VIdEZqK0pQcHdUVWJSS3F2WnZBMVpFWVBvcHlsbnpVazJXRURKelozR1lwQ0YxRDZnRktDS0FTaUwvNUhtNk8wMm5OeHg2b3ZBN09VUWtpRXZtVFUyOTlhNGJ3VStSdTNoWUgrdldwdlV5bDRxaDVNUUUxQVRVRDkvZlowd2hsOWlaOXJ1bHp0OUgzTWU5ZHJSSmNwd0YyN2tqVi9hOFQ4RnFDaXgwV0ZWdGZiRHJkNWJsNFIrb25wY2Vka3htQ0dkUzdic0REM2EwUXZ3a1N6bmlHZnpJamZuNW5BN1ZQOWV4bTEyRmNPdXJwWXdGbVBPTXUweDFjUWZpWUJhMWduaWx6OGlPdDFWNFUxa0F4YTFyWEZKaG5HWER0N1NXN0F1Y0RCUDRPcnVnTGFmd2JTbFdvbzkwclQvYkxRa3dsbmNKWm1ZVmcwM1dkM2Vld21QNnNHUmsvcDUraGNqdGVkcTVyVE1USE9kaUNmMDVLSFhuSEZwY2RvN1NoR3lkd2dPOWJDeGxQV0FWa1lpcWJFRHk2dGlFVVBBOE5YZEZmbUJiZ0tHL3JYa0dzTXVXTzlLMHowbnBqbUY4WEF3YksvcVI0MVYvdmJOckNReE9wUTFEOVVEc1R4dS9nU0VRUnpJWkRhc1BBbGxRMzdxc0x6UmJjRG0veEtYTmJ3ZzJjbEZBOUwrKzJMdHYxY3RzdlA3YzMyMzcrVzdaM21CL2E3L2ZYeHEvMTlQbUc3WEg2Mkx3KzUzYmJiN1dlNy9QaG9QdzVqYnovYjVYQ2VHelphbzU3TGM4U292NENlMVpMdlRCR2MzUWVua2ZJd1dxUE1Fd2trd2JFU0N3eC9tcDMwYlpaMlZkbmdMTForbk1pKy84aDVOWkZVeVQ4T25FNUR6WmtlSFVrUUhOYldOeGsyMWFPbVMvRUUxQVRVQk5UL3dQNEZxdjY1UTJpQVM2WUFBQUFBU1VWT1JLNUNZSUk9ANAOAmF0dHJwaWNpc2xpbmsAMADQBCF1cmkAYTViNmFhMjFmMDAzNDk5NDgzZDk0YjUwMTkxMDdlNTYA0Ac2YXR0cmlkAGE1YjZhYTIxZjAwMzQ5OTQ4M2Q5NGI1MDE5MTA3ZTU2IDEyxOrOqsH1tcK7qrL6z8LSu8WuANAGKWltZ2lkAGE1YjZhYTIxZjAwMzQ5OTQ4M2Q5NGI1MDE5MTA3ZTU2XzEyMV8xMjEAEACFBgAACwAAANAFB25hbWUAs8Lc9sGrANAENmltZwBodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTMxMzgwNjMxMDMsMjY4MzYyODYxOCZmbT01OADQB11wYXJhbXMAd2Q9JUU5JTk5JTg4JUU4JThEJTlGJUU4JThFJUIyJnJzdl9jcT0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmcnN2X2RsPTBfcmlnaHRfcmVjb21fMjEwMzgA0AQHdGlwALPC3PbBqwDQBQ1hdHRyANbcyPO3orXExt7X0wDQCQRhdHRydHlwZQBUQUcAUAjoBAAAYXR0cnBpYwBkYXRhOmltYWdlL2pwZWc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFFb0FBQUFvQ0FZQUFBQlo3R3dnQUFBRFlrbEVRVlI0MnUyWU81S2pPaFNHdjU2YTNNb2Ntb3lRVUR0QU8wQTdZRkhhQWV4QTNvRkNRakk1SkJNcjZCdUFiYkNGSDEwemQ3cXFwWWppb2NkMy92UHJvSS9Qejg5UFVudmFmaVVFQ1ZRQ2xVQWxVQW5VajJtL1gzc3Q0SnFXYm56MjNvNmkwa2dSY0kwRmRiNTI3TFVpZXpTQ2E3QW90QlFRSEkzYm8xVUczbUtPVU5hMzN5L0hlSFF2M3J4dEdPVHo5OTRFdFlSd1dkbDFNY3ZCQVJCSXJYQk5nMU1hcVhPc3NWREM4WGhhOTFwVWFDa0lBYkp6NXlHQXlLZnJURkhYSG1zYWh0WDRQVjVJOUhLaHNYdHpFTnBZbEUrRzd1YldvYXhSa1loK3ZGWnduaU9sd01hVU5VSGN1L3NvclpTeXFhS0FiUWFrbG9qNXZ0dnI2SVRuaUdCV3dLZng4LzRXeUUxd0h5anEyWmkvMzh0VWdkUTFja3RSbDBrWStud1ptVmpxSGlpSzgrT0JNSGEwWmhsZmc0a0t1NkNTVnlWZWdvakgrWXlxbm1CZkZmN0FOdTRVWlRDSGtqcEM2ejFRdmNWMDY5UXg1cnFBUXB5enBhUTNCbHZPVUMrQVBkYjA1TFBmQk5kTWNJVkUxL0tDZTZtdUxVWGRxOU9CMUpGdkZzSDkzeFNWSzJyNXlDRDk3RkVacWlwb3JDTms3MmsyT01kcEhEbVo3dTdaMGovR3J1WDZ5bzVDVGFsbmlTMTJRMVUzaWpxVWY4VE10L3hoVGdkOVExQkl0SWJnL04xRVQ4YkFycUNNTEtqM2dxSVFrS3VGdDNpc2NRaHh2d2xjVXcrRTFPVFdZTGsxNUtXcTVyNnExM2U4TjBFSjl0TzhZSm5Id2RIWURhQjlUaVVlcFo2L1VaUEZaMmR6ZDRRNS9idzlFb29LOWNMQ01sVXhORk0vajlSMGF1OTN2R1hReFZmcnFJQWd2NHh5dkhyVDNQbmRGMFBna0djd09LREhtbzRUQzBVdHpYd0dianVCckFVZ1VHcWdNWVp4cFo1WE54dzFBUXByTmNWMjRPQWFXcDlGNGJ3TktqaEh5TlMxbzQyZElheFNhQzZGQm9BY0ZURzNpNW5qc2EwbnEvUmNWSHBzMnpHeVk3Y2JHVHVMeTllcGN1ZFJzZUNPZ2x5c1BWYjFGbVBHcHdyNkdxaGxNWmdwNm15dGhLYnRHTStEaXJud0c4WExIdUR0RWNvS3JHRmF3NEd5cmxFck01NmZIVXJxUE81UmsvOGNMOHJsVUU1OWJOUmQwK2Z1b3R4SGRkZkgzempoREs2aERaSmFaVkc1ZTJ1WTVyMDlzZS9XUHRKUmNEbzlTS0FTcUFUcXh4emMvZjIyZVdhMC90bUwxbTlwMTF2K2d2QmFZZmdqUVUwcTQxdlVXdDhYbExjMGczempIeStaZWFyTUh4MkRiTGJkdi9HcWxIb3A5UktvQkNwVjVsODA5a09wMHE2WFVpK0JTcUJTUzZEK1hQc1BPcmtZWWdqTVRoZ0FBQUFBU1VWT1JLNUNZSUk9ANAOAmF0dHJwaWNpc2xpbmsAMADQBCF1cmkANTg5NTIyMGVmZGVhNDdhYmExOGM0YjExZDI5OGMxOGMA0AcuYXR0cmlkADU4OTUyMjBlZmRlYTQ3YWJhMThjNGIxMWQyOThjMThjINbcyPO3orXExt7X0wDQBilpbWdpZAA1ODk1MjIwZWZkZWE0N2FiYTE4YzRiMTFkMjk4YzE4Y18xMjFfMTIxABAAaAcAAAsAAADQBQVuYW1lANT4va0A0AQ2aW1nAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9MzMzNzY5NjU3MywyODMxMTAyODQyJmZtPTU4ANAHVHBhcmFtcwB3ZD0lRTYlOUIlQkUlRTYlQjElOUYmcnN2X2NxPSVFNSU4OCU5OCVFNSVCRSVCNyVFNSU4RCU4RSZyc3ZfZGw9MF9yaWdodF9yZWNvbV8yMTAzOADQBAV0aXAA1Pi9rQDQBQ9hdHRyAMDPz7e5x8irxNzR3dSxANAJBGF0dHJ0eXBlAFRBRwBQCNQFAABhdHRycGljAGRhdGE6aW1hZ2UvanBlZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUVvQUFBQW9DQVlBQUFCWjdHd2dBQUFFRkVsRVFWUjQydTFaUFpxYk1CQjl5YmM5Nmx4Q1IwbXBHNkFid0ExMHA5VUpMRTVnY1FLcnBLU3lLRjJ0ZkFKU2dFRmc1TC9kT01tR3FmZ1FRcU0zYjM0MCt0RzJiWXRWYnNyUEZZSVZxQldvRmFnVnFCV28vMGJlbnBwbEZPU1JJcWZrc1hsV1Erb05HTkVvVElRc3B4ai9ZS0JFaWNZM04waG0zODlWRWlpYkVDbG5pSllYaDVZRkxPVmcwVlNmbkVYZGMxR0JwTTc0cDRHNmlZZEVVWjNHRjJFSzdxeE9hQTRlYTBpcHdTYWI5MjNVUU1uajFmVktteUJMTFFxcEZ3RTFTZ0dNZ3hFREpXckU1M1dhRWtMMGh1RGNhNGdmZHhlY1JrR1VqY2ZZR2ZLNGhsU1liWHhtdFg3RGhGU29HbWN1SmN1TUdsalV6YU1YQUhRc3FZaGpDS01nU2t3QTc5ZzJVenBNd2VuUjBXMnU2N09NaWhnNFgzSzlUbGxoUnRld1drS0JkZVBXQWdSVEVDZ0haMHVMT0l5eUdsTGRObHlZY3ZCb3BtZW1JWVdBN28wUU1RNitNRi9WTS81WUM1RDRlVVpkdU5JVjZSZ0M2STVlaUdzSnZjbDd2M2VaWWFHbHhpWm5pSzZ3OVFMS2xDT3VCVW9rU0d3RnYxb2hrc1NpTWhFeUJxaWl3bW5PS0lZTEZvZWVHSVgyS2Zsbzk5djM5djE5MXg2OG4remI3WGJYN3JiYmR2L2h6dXZtZk95MzdmWThjTmkxMi8yaDNVKytuZjlyM3g3MjIzWjM4QzNuL004emZ4Zzk3TnIzM2VHaEhiODltdTA2eXdkSU1nNU9Sc1lOcmpaR2JMQklvakFSeHRjRUcySnhOQnJhUkdBNUdkd2xqeXkwT2FFcUJDcFAxaU0wQjNzMnc1d3FGTUw1Y3hoMys2bmpMcjcxV1E5RHpId2lSZzNCTUV5UUJCWmdPU2pwQSttcG8zRkdGMXpXbm9DVFFXM3BBQlloUUZrYUpGbStrR0VDSkZtT0N6Mlg0dFdpdXhad3NRamNUYnZsaFZFUWRmL1JuVm52N2I0NGZnNkdGbHBXdmRXbnJPbzI0MlFNbzhhVXJRMW9uL1YwZFFLQ0JER1p4eXdBdU00b2IzTHhzZm9XbythbHk1ZGt2UnRXdDdWeE1vYUJLaTJTaklFUUlLMGx0RG5DbEYxQmw5WUNTc2ZJTnpVYUVqdnVkSVZSZWdPQ1Q0aVBVWGRtdlFlQklvZ2pvRmkwZW9Ba0l6MlpTaURsdzRZalJsR0xHcFR6THZWSEdZNnljNU13WmRjcitUNWJCVWwyUjAwM2RiMnh4cnVzL29PRUFsR01zT3hkYjhoNjdKTUY1M29vWG1VRmFnVnFCV29GNnY5czNEMHJDeTJRNGRCOTBjaTdzNkdIYTgyNnI1TS9VQjdjMnZqOEZEOXJ0RjM4eXpmMkx6T3FLei9CT0lkUkFuVzgzTkt3V2tKUDNqUW8zYXB3eHFqNEJWcS9sRkZHQ1dneUhsUjlmUzV2VCtnUHlzdGR6MnFKd3RKSkR4M2VWdTk5VGNQQTB4cjV4MlBVSGJIS09kRmI3WFpJbHhQRVV6ZENmMzJNR2xvWldMNDhzQnBTWDJma1ZlQytDMUMyTmlBeEJXQXVla1ROK1RsTS9mUHRDZGg4OXpvS0ZwTzIxY09NTXFnYm9Ha0UxSXNEL3R1TDZRU0RDT3djVHU1ZzFMbFBmZzdxNStzcG93UkVlUzQ0eVc5WC9hWEJmR3pYb3UrM0wzUTBuZnM2ZWh3em5qK3o5VWxoZGh2OWpiTGVlaWhlZ1ZxQldtVUY2cXZrRitYN2ZPVU53WW90QUFBQUFFbEZUa1N1UW1DQwDQDgJhdHRycGljaXNsaW5rADAA0AQhdXJpAGEwM2NiZjE2MGRiNjRhOGNhMmQ4OWI4MzA3N2NiYmRkANAHMGF0dHJpZABhMDNjYmYxNjBkYjY0YThjYTJkODliODMwNzdjYmJk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bS9pdC91PTI0OTAyNjE5OTUsMjQyMDMxOTM0MiZmbT01OADQBilpbWdpZAAwYTRhMjAyYjVmOWY0NWQ2OGVkZDQ1M2MzMmI3NDE1ZF8xMjFfMTIxABAA3wAAAAYAAADQBgdlbmFtZQDV1LG+y64A0AQhdXJpADM5Y2RlNzhiNjFmMzQ2YjU5MzE0NWNkMWQxNmIyMWVmANAKB2p1bXBxdWVyeQDV1LG+y64A0AcTYXBwZW5kANOyxvi5pr/avLzA1sb30d3UsQDQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0yNzMyNjM3NDg5LDI1Mjk3MjI4NTEmZm09NTgA0AYpaW1naWQAMzljZGU3OGI2MWYzNDZiNTkzMTQ1Y2QxZDE2YjIxZWZfMTIxXzEyMQAQANsAAAAGAAAA0AYHZW5hbWUA1dSxvsm9ANAEIXVyaQA1MjIyMzVhMTgyMjI0MTg4YmRjYzBhYjdkMmRiOGNiYQDQCgdqdW1wcXVlcnkA1dSxvsm9ANAHEWFwcGVuZAC0+rHt1/fGt8/ntOWwrsfpANAHNHBpY3VybABodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTk1NDM3NzA0OCw2MzI2NTQ5NTMmZm09NTgA0AYpaW1naWQANTIyMjM1YTE4MjIyNDE4OGJkY2MwYWI3ZDJkYjhjYmFfMTIxXzEyMQAQAN0AAAAGAAAA0AYHZW5hbWUAs8LOsPaqANAEIXVyaQBlOWNmYjIzNjM3MjA0ZTQzOGNiMDE3MDAxOTY0ZGI1MgDQCgdqdW1wcXVlcnkAs8LOsPaqANAHEWFwcGVuZAC0+rHt1/fGt8G1yMvQ9dPvANAHNnBpY3VybABodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTI1ODQ0MDA0MjEsMTM2Njc2MTMyNCZmbT01OADQBilpbWdpZABlOWNmYjIzNjM3MjA0ZTQzOGNiMDE3MDAxOTY0ZGI1Ml8xMjFfMTIxABAA3wAAAAYAAADQBgdlbmFtZQC439Sy1LIA0AQhdXJpADE1ODdmNDVjZTY5NzQwM2FhOTY4OGY3NGU0NjI1NTFlANAKB2p1bXBxdWVyeQC439Sy1LIA0AcTYXBwZW5kANXU09bNotauxt65+sPxxa7J8QDQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0yNDg0NjE2NzE5LDExODkyNTEwNjkmZm09NTgA0AYpaW1naWQAMTU4N2Y0NWNlNjk3NDAzYWE5Njg4Zjc0ZTQ2MjU1MWVfMTIxXzEyMQAQAOEAAAAGAAAA0AYHZW5hbWUA0KHQoda+ANAEIXVyaQBhNThmODE3NWU0YTA0ZDJhODQxMjM1NzYwNDFkOGE0NgDQCgdqdW1wcXVlcnkA0KHQoda+ANAHFWFwcGVuZADRx9be0KHQ/bfnwdbWvtOx1q7X0wDQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0zODI1MjQ3NTQyLDM3MzMwODk3OTkmZm09NTgA0AYpaW1naWQAYTU4ZjgxNzVlNGEwNGQyYTg0MTIzNTc2MDQxZDhhNDZfMTIxXzEyMQAQAOEAAAAGAAAA0AYHZW5hbWUAy9XT0MXzANAEIXVyaQBlMDhmOWQyOGRiZWE0YmNhOTkyZmRlMDQ0M2ZjMWM2MADQCgdqdW1wcXVlcnkAy9XT0MXzANAHFWFwcGVuZADQobuittOh+s7lsKK456H607C12wDQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0zMjc0MDMwMTczLDE1MTA5NDc0MTImZm09NTgA0AYpaW1naWQAZTA4ZjlkMjhkYmVhNGJjYTk5MmZkZTA0NDNmYzFjNjBfMTIxXzEyMQAQAN0AAAAGAAAA0AYHZW5hbWUAtsXeyLriANAEIXVyaQBlMWVhNjg5MjFiNzQ0ZGEyOTkxYTRjMjVjMjk1OTc5NgDQCgdqdW1wcXVlcnkAtsXeyLriANAHEWFwcGVuZACxu7PGzqq3rbDmwfW1wruqANAHNnBpY3VybABodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTQxNzk2MzY2MTcsMzg0MjAxNjYxNyZmbT01OADQBilpbWdpZABlMWVhNjg5MjFiNzQ0ZGEyOTkxYTRjMjVjMjk1OTc5Nl8xMjFfMTIxABAA3QAAAAYAAADQBgVlbmFtZQDL79mzANAEIXVyaQA1ZTc4M2ZmY2Q2ZmE0NDRiYWZiYjIwZWM1OWY4NDk5MgDQCgVqdW1wcXVlcnkAy+/ZswDQBxVhcHBlbmQA0/G529L0s8nD+9Xni9a0q7zTw+EA0Ac2cGljdXJsAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9MjU4MjkyNzA5MiwxOTQxOTk3NjMxJmZtPTU4ANAGKWltZ2lkADVlNzgzZmZjZDZmYTQ0NGJhZmJiMjBlYzU5Zjg0OTkyXzEyMV8xMjEAEADaAAAABgAAANAGB2VuYW1lANXFvNK71ADQBCF1cmkANDIxMGVjZWY4NTMyNDgzMTkyMmY0ZGM1M2QwYWUwZmMA0AoHanVtcHF1ZXJ5ANXFvNK71ADQBw9hcHBlbmQA1tC5+tb4w/vE0NHd1LEA0Ac1cGljdXJsAGh0dHA6Ly90MTIuYmFpZHUuY29tL2l0L3U9ODk1NTA1MDkwLDE4OTA2MTE1MjUmZm09NTgA0AYpaW1naWQANDIxMGVjZWY4NTMyNDgzMTkyMmY0ZGM1M2QwYWUwZmNfMTIxXzEyMQAQAOAAAAAGAAAA0AYHZW5hbWUAwu3SwaxQANAEIXVyaQA5YmEzMTg2NWI1ZDQ0ZTZhOWUyOGNlMDAyMjViMjM2YwDQCgdqdW1wcXVlcnkAwu3SwaxQANAHFWFwcGVuZADT687E1cK1xLCux9LQ0MfS1eTPpwDQBzVwaWN1cmwAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0xNjU3NjYwNDMwLDI5OTc2NTkyMiZmbT01OADQBilpbWdpZAA5YmEzMTg2NWI1ZDQ0ZTZhOWUyOGNlMDAyMjViMjM2Y18xMjFfMTIxABAA3gAAAAYAAADQBgdlbmFtZQDW3Mjzt6IA0AQhdXJpAGYyMjdmYmQxYjQxMTQyYmRhN2VmOWJkM2EzMmZmZGM0ANAKB2p1bXBxdWVyeQDW3Mjzt6IA0AcTYXBwZW5kAM2swfW1wruq1vfR3b2tuv7H6QDQBzVwaWN1cmwAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT02MjU0NjYwNjksMTc0NjQ3NjEzMyZmbT01OADQBilpbWdpZABmMjI3ZmJkMWI0MTE0MmJkYTdlZjliZDNhMzJmZmRjNF8xMjFfMTIxABAA2AAAAAYAAADQBgdlbmFtZQDX3tXXwfoA0AQhdXJpADliODk3MDU2Mzg5YjQ3MjNhMWE2NWVmNzE2ZDYxNGQ4ANAKB2p1bXBxdWVyeQDX3tXXwfoA0AcNYXBwZW5kALrpvNKw4LXE0rvUsQDQBzVwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT02NTE3NDk0MzksMjk3MjkwOTYwNSZmbT01OADQBilpbWdpZAA5Yjg5NzA1NjM4OWI0NzIzYTFhNjVlZjcxNmQ2MTRkOF8xMjFfMTIxABAA3AAAAAYAAADQBgVlbmFtZQC6+rjoANAEIXVyaQBmYTUyMjYyMzYwZGI0MzQ5OWRhNDE0MDYyMTUwN2I1NwDQCgVqdW1wcXVlcnkAuvq46ADQBxVhcHBlbmQAz8m9o7rAy6zJ7sfptcTA7uXQ0qMA0Ac1cGljdXJsAGh0dHA6Ly90MTAuYmFpZHUuY29tL2l0L3U9MjE4OTQ5NzYwNSw2OTk1NDQyNDQmZm09NTgA0AYpaW1naWQAZmE1MjI2MjM2MGRiNDM0OTlkYTQxNDA2MjE1MDdiNTdfMTIxXzEyMQAUD2l0ZW0jbnVtI2JhaWR1ABAAAADQCwJzbGlkZV90eXBlADEA0AwCYXBwZW5kX3R5cGUAMgAQAEMPAAAJAAAA0AYLdGl0bGUAxuTL+8jLu7nL0QDQBEJ1cmwAaHR0cDovL3d3dy5iYWlkdS5jb20vcz93ZD0lRTUlODglOTglRTUlQkUlQjclRTUlOEQlOEUmc3JjaWQ9MjEwMzgA0AMHY3EAwfW1wruqACAKNwAAAHRpdGxlaW5mbwABAAAAEAAtAAAAAgAAANAHC2FwcGVuZADG5Mv7yMu7ucvRANAKB2p1bXBxdWVyeQDB9bXCu6oAFBR0aXRsZWluZm8jbnVtI2JhaWR1AAEAAAAgBTMOAABpdGVtABAAAAAQAO0AAAAGAAAA0AYPZW5hbWUAtLrN7brayavI/bfW1tMA0AQhdXJpAGE4ZTY4NDIyZDZkOTRhNjBhZmJiNzY4YjdkNWNmOWE5ANAKD2p1bXBxdWVyeQC0us3tutrJq8j9t9bW0wDQBxNhcHBlbmQA0evK07S6ze21xNK7tPOw3LHKANAHNHBpY3VybABodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTg5MjM5MTI4MywxOTIzMjQyMjUmZm09NTgA0AYpaW1naWQAYThlNjg0MjJkNmQ5NGE2MGFmYmI3NjhiN2Q1Y2Y5YTlfMTIxXzEyMQAQAOEAAAAGAAAA0AYHZW5hbWUA1uzA9tm7ANAEIXVyaQBhNWI2YWEyMWYwMDM0OTk0ODNkOTRiNTAxOTEwN2U1NgDQCgdqdW1wcXVlcnkA1uzA9tm7ANAHFWFwcGVuZAAxMsTqzqrB9bXCu6qy+s/C0rvFrgDQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0yNzQzMjM0NTk5LDI5MTA5NTUzNjUmZm09NTgA0AYpaW1naWQAYTViNmFhMjFmMDAzNDk5NDgzZDk0YjUwMTkxMDdlNTZfMTIxXzEyMQAQANkAAAAGAAAA0AYHZW5hbWUAs8Lc9sGrANAEIXVyaQA1ODk1MjIwZWZkZWE0N2FiYTE4YzRiMTFkMjk4YzE4YwDQCgdqdW1wcXVlcnkAs8Lc9sGrANAHDWFwcGVuZADW3Mjzt6K1xMbe19MA0Ac2cGljdXJsAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9MzEzODA2MzEwMywyNjgzNjI4NjE4JmZtPTU4ANAGKWltZ2lkADU4OTUyMjBlZmRlYTQ3YWJhMThjNGIxMWQyOThjMThjXzEyMV8xMjEAEADXAAAABgAAANAGBWVuYW1lANT4va0A0AQhdXJpAGEwM2NiZjE2MGRiNjRhOGNhMmQ4OWI4MzA3N2NiYmRkANAKBWp1bXBxdWVyeQDU+L2tANAHD2FwcGVuZADAz8+3ucfIq8Tc0d3UsQDQBzZwaWN1cmwAaHR0cDovL3QxMS5iYWlkdS5jb20vaXQvdT0zMzM3Njk2NTczLDI4MzExMDI4NDImZm09NTgA0AYpaW1naWQAYTAzY2JmMTYwZGI2NGE4Y2EyZDg5YjgzMDc3Y2JiZGRfMTIxXzEyMQAQAN0AAAAGAAAA0AYFZW5hbWUAu8ayswDQBCF1cmkAZTY1OThkYzc3NTA4NDQyOGEyZGYwNTAxNjZiMTg1ZDQA0AoFanVtcHF1ZXJ5ALvGsrMA0AcVYXBwZW5kANLyt+i/8bXEyq/Nt7raxqTX37rsANAHNnBpY3VybABodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTE5MDIwOTkwMTIsMTY3MDA1MDk0MiZmbT01OADQBilpbWdpZABlNjU5OGRjNzc1MDg0NDI4YTJkZjA1MDE2NmIxODVkNF8xMjFfMTIxABAA2QAAAAYAAADQBgVlbmFtZQDB9ezHANAEIXVyaQBjZjgwMjg3ZDg1NzI0ZWQwYjliY2YyNTkzN2JlZjJiMwDQCgVqdW1wcXVlcnkAwfXsxwDQBxFhcHBlbmQAu6jR+dKv0q+2urHIzPS38gDQBzZwaWN1cmwAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0yNTMyMTUzMDAyLDQyMTU4NTU0MDYmZm09NTgA0AYpaW1naWQAY2Y4MDI4N2Q4NTcyNGVkMGI5YmNmMjU5MzdiZWYyYjNfMTIxXzEyMQAQAN8AAAAGAAAA0AYHZW5hbWUA1tzQx7PbANAEIXVyaQBjZDBmNTdmOWQ2MmQ0MWEyYmE2YjdiNmM3NzRjOWNlOADQCgdqdW1wcXVlcnkA1tzQx7PbANAHE2FwcGVuZAC1sdauzt7AorXEz7K+58zszfUA0Ac2cGljdXJsAGh0dHA6Ly90MTEuYmFpZHUuY29tL2l0L3U9MTM4Mzc0NDA0MCwxNjUwNTQ3NzI4JmZtPTU4ANAGKWltZ2lkAGNkMGY1N2Y5ZDYyZDQxYTJiYTZiN2I2Yzc3NGM5Y2U4XzEyMV8xMjEAEADdAAAABgAAANAGBWVuYW1lALPJwfoA0AQhdXJpADE1ZjhmNjM5ZTYxMTRjN2FiMjAwMjZkOTg4ZTk3ZTY1ANAKBWp1bXBxdWVyeQCzycH6ANAHFWFwcGVuZAC5+rzKuaa38r7e0Me8sLTIyca80gDQBzZwaWN1cmwAaHR0cDovL3QxMC5iYWlkdS5jb20vaXQvdT0zNDk5MzEyMjY2LDM5MzQ2MTIzNTgmZm09NTgA0AYpaW1naWQAMTVmOGY2MzllNjExNGM3YWIyMDAyNmQ5ODhlOTdlNjVfMTIxXzEyMQAQANoAAAAGAAAA0AYHZW5hbWUAwdbH4M+8ANAEIXVyaQA0YzUwYjYwNzMwMTA0NGQ3YTQ0MTc1NTViZmQxNmQ5YgDQCgdqdW1wcXVlcnkAwdbH4M+8ANAHD2FwcGVuZAC2q8TP0ce12tK7w8DFrgDQBzVwaWN1cmwAaHR0cDovL3QxMi5iYWlkdS5jb20vaXQvdT0xNzA3Nzk2MTAwLDU3NDczMTU0NCZmbT01OADQBilpbWdpZAA0YzUwYjYwNzMwMTA0NGQ3YTQ0MTc1NTViZmQxNmQ5Yl8xMjFfMTIxABAA4QAAAAYAAADQBgdlbmFtZQDDt9Het7wA0AQhdXJpAGEyNWZhMWQ2ZWNjZjRmZjJhNjRmOTU4Mzk3YjZmMDg0ANAKB2p1bXBxdWVyeQDDt9Het7wA0AcVYXBwZW5kALuq0+/A1syzte7Mw7y20tXK9bzSANAHNnBpY3VybABodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTM5Mzk3NTc5NjQsMjk5NzQxMTc2NCZmbT01OADQBilpbWdpZABhMjVmYTFkNmVjY2Y0ZmYyYTY0Zjk1ODM5N2I2ZjA4NF8xMjFfMTIxABAA2gAAAAYAAADQBgdlbmFtZQDP8ruqx78A0AQhdXJpADUyZDY0Y2YyNGFiYjQ1NjA4YmFkYTc2YzNhNDJjYTU3ANAKB2p1bXBxdWVyeQDP8ruqx78A0AcPYXBwZW5kANbQufrQx7yvzcXW98+vANAHNXBpY3VybABodHRwOi8vdDEwLmJhaWR1LmNvbS9pdC91PTM2ODAwMDQxNTAsNzM4NjE2MjM4JmZtPTU4ANAGKWltZ2lkADUyZDY0Y2YyNGFiYjQ1NjA4YmFkYTc2YzNhNDJjYTU3XzEyMV8xMjEAEADVAAAABgAAANAGB2VuYW1lANXFufrI2QDQBCF1cmkAYzUxZjY4YmJmN2I2NDU3YjhkNTAyM2VlOGE4NGE2ZmEA0AoHanVtcHF1ZXJ5ANXFufrI2QDQBwlhcHBlbmQAyfrHsLrD09EA0Ac2cGljdXJsAGh0dHA6Ly90MTAuYmFpZHUuY29tL2l0L3U9MzM0NDk1NDAwNCw0MjE2MDI3NzIzJmZtPTU4ANAGKWltZ2lkAGM1MWY2OGJiZjdiNjQ1N2I4ZDUwMjNlZThhODRhNmZhXzEyMV8xMjEAEADfAAAABgAAANAGB2VuYW1lALnY1q7B1QDQBCF1cmkANDBiNzAzY2NlNGYxNGI5ZDk3ZDE2MzZlMTg4OTQ5NmIA0AoHanVtcHF1ZXJ5ALnY1q7B1QDQBxVhcHBlbmQAu/HU3sTQyMvA7c/rw87W0MfpyMsA0Ac0cGljdXJsAGh0dHA6Ly90MTIuYmFpZHUuY29tL2l0L3U9MjEwODIzOTkxOSw4MDIyMTQ1MCZmbT01OADQBilpbWdpZAA0MGI3MDNjY2U0ZjE0YjlkOTdkMTYzNmUxODg5NDk2Yl8xMjFfMTIxABAA2wAAAAYAAADQBgdlbmFtZQDBurOvzrAA0AQhdXJpADY1M2ZiZTVhN2U5MzQ4OWRiNTY5ODRjNDM3NTRiMjc3ANAKB2p1bXBxdWVyeQDBurOvzrAA0AcPYXBwZW5kAL75zqrO3s/fzuW7or2rANAHNnBpY3VybABodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTMxMTcwOTMwMjMsMjcyMjA0Nzc2MSZmbT01OADQBilpbWdpZAA2NTNmYmU1YTdlOTM0ODlkYjU2OTg0YzQzNzU0YjI3N18xMjFfMTIxABAA4QAAAAYAAADQBgdlbmFtZQDN9dfmz80A0AQhdXJpADA1NjAzMmRlZTIwNDRmNTdiNTIwNzk2MzNkYzFjY2Q5ANAKB2p1bXBxdWVyeQDN9dfmz80A0AcVYXBwZW5kAMvY0dXH5bS/xa7J8bK7wM+0q8bmANAHNnBpY3VybABodHRwOi8vdDExLmJhaWR1LmNvbS9pdC91PTE2MTI1NTQ1NDcsMTQzOTQ3MTI5OSZmbT01OADQBilpbWdpZAAwNTYwMzJkZWUyMDQ0ZjU3YjUyMDc5NjMzZGMxY2NkOV8xMjFfMTIxABAA2gAAAAYAAADQBgVlbmFtZQDA+9bHANAEIXVyaQBiZTBiNGQ2NjVkNmE0MzExODNjYmNhNmFkYzdlZmFhMQDQCgVqdW1wcXVlcnkAwPvWxwDQBxNhcHBlbmQA1tC5+s/juNvR3dSxwPvDwMjLANAHNXBpY3VybABodHRwOi8vdDEyLmJhaWR1LmNvbS9pdC91PTEyMzMwMTA4MDUsNTM2ODUxOTMwJmZtPTU4ANAGKWltZ2lkAGJlMGI0ZDY2NWQ2YTQzMTE4M2NiY2E2YWRjN2VmYWExXzEyMV8xMjEAFA9pdGVtI251bSNiYWlkdQAQAAAA0AsCc2xpZGVfdHlwZQAxANAMAmFwcGVuZF90eXBlADIAFA9jYXJkI251bSNiYWlkdQACAAAAFAdTaXRlSWQAblIAAA==\u0000"}],"ResultNum":2}
\ No newline at end of file
package gss.message;
//------------------------------------gss_src_req_t---------------------------------
//struct gss_src_req_t
//{
// string TransQuery[] = optional(); /**< transquery from da tranfered by us */
// int32_t ExtType[] = optional(); /**< 扩展query类型 */
// int32_t SrcID = optional(); /**< table id */
// int32_t SrcId = optional(); /**< table id */
// int32_t Pos = optional(); /**< pos */
// int32_t Place = optional(); /**< place */
// int32_t Degree = optional(); /**< degree */
// string Key = optional(),default(""); /**< us建议key */
// string ReqKey = optional(),default(""); /**< us建议 ReqKey */
// int32_t QueryType = optional(),default(0); /**< 类型,default=0 */
// binary HighLight = optional(),default(""); /**< da飘红词 */
// string RetFormat = optional(),default("html"); /**< 回传格式 */
// string TagFilter = optional(),default(""); /**< Tag过滤信息 */
// //SPEC REQ
// int32_t SpReqType = optional(),default(0); /**< 特殊请求类型,正常为0 */
// //FRO ZHIXIN USE
// string UriKey = optional(); /**< UriKey 知心卡片使用 */
// string EntityName = optional(); /**< 实体名 知心卡片使用 */
//};
message gss_src_req_t {
repeated string TransQuery = 1; /**< transquery from da tranfered by us */
repeated int32 ExtType = 2; /**< 扩展query类型 */
optional int32 SrcID = 3; /**< table id */
//optional int32 SrcId = 4; /**< table id */
optional int32 Pos = 5; /**< pos */
optional int32 Place = 6; /**< place */
optional int32 Degree = 7; /**< degree */
optional string Key = 8; /**< us建议key */
optional string ReqKey = 9; /**< us建议 ReqKey */
optional int32 QueryType = 10; /**< 类型,default=0 */
optional bytes HighLight = 11; /**< da飘红词 */
optional string RetFormat = 12 [default ="html"]; /**< 回传格式 */
optional string TagFilter = 13; /**< Tag过滤信息 */
//SPEC REQ
optional int32 SpReqType = 14; /**< 特殊请求类型,正常为0 */
//FRO ZHIXIN USE
optional string UriKey = 15; /**< UriKey 知心卡片使用 */
optional string EntityName = 16; /**< 实体名 知心卡片使用 */
};
//------------------------------------终端 ua 信息:us_gss_req_t---------------------------------
//struct ua_info_t
//{
// string ua_os = optional(); /**< 操作系统 */
// string ua_browser = optional(); /**< 浏览器 */
// string ua_modal = optional(); /**< 机型 */
// string ua_measure = optional(); /**< 尺寸 */
// int32_t ua_res_x = optional(); /**< 分辨率宽 */
// int32_t ua_res_y = optional(); /**< 分辨率高 */
// binary ua_ext = optional(); /**< 扩展(预计会放操作系统版本os_version、浏览器版本browser_version)*/
//};
message ua_info_t {
optional string ua_os = 1; /**< 操作系统 */
optional string ua_browser = 2; /**< 浏览器 */
optional string ua_modal = 3; /**< 机型 */
optional string ua_measure = 4; /**< 尺寸 */
optional int32 ua_res_x = 5; /**< 分辨率宽 */
optional int32 ua_res_y = 6; /**< 分辨率高 */
optional bytes ua_ext = 7; /**< 扩展(预计会放操作系统版本os_version、浏览器版本browser_version)*/
};
//------------------------------------app_info_t------------------------------------------------
//struct app_info_t
//{
// string package; /*应用的packagename*/
// int32_t version; /*应用的version code*/
// uint32_t signmd5; /*包体签名*/
//};
message app_info_t {
required string package = 1; /*应用的packagename*/
required int32 version = 2; /*应用的version code*/
required uint32 signmd5 = 3; /*包体签名*/
}
//------------------------------------us请求gss结构体:us_gss_req_t---------------------------------
//struct us_gss_req_t
//{
// string OriginQuery; /**< 原始query */
// int32_t UserIP; /**< 用户IP */
// int32_t TimingNeed; /**< 时效性查询 */
// uint64_t QueryID64 = optional(),default(0); /**< QueryID */
// string ClientName = optional(),default("unknow"); /**< 调用方名称 */
// int32_t ResNum = range(0,2000),default(20),optional(); /**< 翻页参数,当页结果数 */
// int32_t PageNum = range(0,2000),default(0),optional(); /**< 翻页参数,结果偏移量 */
// int32_t ctpl_or_php = optional(),default(0),range(0,1); /**< 是否smarty渲染 */
// int32_t SeType = optional(),default(0); /**< 请求类型 0:US, 1:US_MID, 2:UI */
// //int32_t KeepAlive; /**< 保持连接 */
// string TemplateName; /**< 模版名 ex. baidu wisexmlnew */
// int32_t sid[] = optional(); /**< 抽样id */
// binary UrlParaPack = optional(); /**< Uri参数包 */
// binary gssqa = optional(); /**< 经us透传的DA分析结果 */
// string Cookie = optional(),default(""); /**< 用户cookie */
// string province_name = optional(); /**< 省份信息 */
// string city_name = optional(); /**< 城市信息 */
// string isp_name = optional(); /**< 运营商信息 */
// uint32_t SrcNum; /**< 请求table数量 */
// string From = optional(),default("www"); /**< 请求来源 */
// string Fmt = optional(),default("html"); /**< 请求格式 */
// binary HighLight = optional(),default(""); /**< da飘红词 */
// int32_t NeedHilightStr = optional(),default(0); /**< 是否回传飘红词 */
// gss_src_req_t SrcArr[] = optional(); /**< table请求信息 */
// //国际化新增参数
// int64_t resultLang = optional(); /**< 用户需要的结果语言设置 */
// int64_t resultLocale = optional(); /**< 用户需要的结果地域 */
// //终端app 信息
// app_info_t AppInfoArr[] = optional(); /**< 用户安装的app信息*/
// //终端ua 信息
// ua_info_t uaInfo = optional(); /**< 请求的终端信息 */
// string useragent_full = optional(); /**< 请求的终端全部信息 */
// //百度账号信息
// int32_t uid = optional();
// string uname = optional();
// int32_t open_gssda_recall = optional();
// int32_t prefetch_flag = optional(); /**< 针对wise-us。值为1表示预取请求,值为0表示正常检索请求 */
//};
// pb for us_gss_req_t:
message us_gss_req_t {
required string OriginQuery = 1; /**< 原始query */
required int32 UserIP = 2; /**< 用户IP */
required int32 TimingNeed = 3; /**< 时效性查询 */
optional uint64 QueryID64 = 4 [default = 0]; /**< QueryID */
optional string ClientName = 5 [default = "unknow"]; /**< 调用方名称 */
//reserved 6 - 10
optional int32 ResNum = 11 [default = 20]; /**< 翻页参数,当页结果数 */
optional int32 PageNum = 12 [default = 0]; /**< 翻页参数,结果偏移量 */
optional int32 ctpl_or_php = 13 [default = 0]; /**< 是否smarty渲染 */
optional int32 SeType = 14 [default = 0]; /**< 请求类型 0:US, 1:US_MID, 2:UI */
//int32_t KeepAlive; /**< 保持连接 */
required string TemplateName = 15; /**< 模版名 ex. baidu wisexmlnew */
repeated int32 sid = 16; /**< 抽样id */
optional bytes UrlParaPack = 17; /**< Uri参数包*/
optional bytes gssqa = 18; /**< 经us透传的DA分析结果 */
optional string Cookie = 19; /**< 用户cookie */
//reserved 20 - 30
optional string province_name = 31; /**< 省份信息 */
optional string city_name = 32; /**< 城市信息 */
optional string isp_name = 33; /**< 运营商信息 */
required uint32 SrcNum = 34; /**< 请求table数量 */
optional string From = 35 [default = "www"]; /**< 请求来源 */
optional string Fmt = 36 [default = "html"]; /**< 请求格式 */
optional bytes HighLight = 37; /**< da飘红词 */
optional int32 NeedHilightStr = 38 [default = 0]; /**< 是否回传飘红词 */
repeated gss_src_req_t SrcArr = 39; /**< table请求信息 */
//国际化新增参数
optional int64 resultLang = 40; /**< 用户需要的结果语言设置 */
optional int64 resultLocale = 41; /**< 用户需要的结果地域 */
//终端app 信息
repeated app_info_t AppInfoArr = 42; /**< 用户安装的app信息*/
//终端ua 信息
optional ua_info_t uaInfo = 43; /**< 请求的终端信息 */
optional string useragent_full = 44; /**< 请求的终端全部信息 */
//百度账号信息
optional int32 uid = 45;
optional string uname = 46;
optional int32 open_gssda_recall = 47;
optional int32 prefetch_flag = 48; /**< 针对wise-us。值为1表示预取请求,值为0表示正常检索请求*/
//reserved 50 - 70
//added by new gss:
//for service distribution:
optional string service_name = 71;
//for normalized caller:
optional string caller = 72;
//for parsing UrlParaPack:
optional UserAgent user_agent = 73;
};
/** uri相关请求参数, gss代码中定义的结构体: */
//struct uri_req_t {
// unsigned int uri_len; /**< uri长度 */
// char uri[US2GSS_MAX_URI_LEN]; /**< uribuffer */
// u_int uri_sign[2]; /**< 对uri的签名 */
// char dsp[GSS_GEN_STR_LEN]; /**< dsp参数 */
// npoint_t crd; /**< 用户百度地图墨卡托坐标 for lbs */
// char os[GSS_GEN_STR_LEN]; /**< os操作系统参数 */
// char osv[GSS_GEN_STR_LEN]; /**< osv操作系统版本参数 */
// char mb[GSS_GEN_STR_LEN]; /**< mb浏览器参数 */
// char mbv[GSS_GEN_STR_LEN]; /**< mbv浏览器版本参数*/
// int apn; /**< opendata api的co参数中传递的翻页信息类似大搜索的pn */
// int arn; /**< opendata api的co参数中传递的翻页信息类似大搜索的rn */
// char cuid[GSS_GEN_STR_LEN]; /**< 移动用户唯一标识*/
// char net_type[GSS_GEN_STR_LEN]; /**< 移动网络类型,0=>unknown,1=>wifi, 2=>2G, 3=>3G*/
// int ignore_caller_auth; /**< 忽略调用方认证 */
//};
// 对应uri_req_t中的部分信息:
message UserAgent {
optional string dsp = 1; /**< dsp参数 */
optional string os = 2; /**< os操作系统参数 */
optional string osv = 3; /**< osv操作系统版本参数 */
optional string mb = 4; /**< mb浏览器参数 */
optional string mbv = 5; /**< mbv浏览器版本参数*/
optional int32 apn = 6; /**< opendata api的co参数中传递的翻页信息类似大搜索的pn */
optional int32 arn = 7; /**< opendata api的co参数中传递的翻页信息类似大搜索的rn */
optional string cuid = 8; /**< 移动用户唯一标识*/
optional string net_type = 9; /**< 移动网络类型,0=>unknown,1=>wifi, 2=>2G, 3=>3G*/
};
//------------------------------------gss给us子链接结构体: sub_url_t---------------------------------
//struct sub_url_t
//{
// string SubURL; /**< sub url */
// string SubURI = optional(); /**< sub uri */
// string SubName = optional();
// string SubPath = optional();
// int32_t SiteId = optional(); /**< 子链接site id */
// string SubEx = optional(); /**< extend */
//};
message sub_url_t {
required string SubURL = 1; /**< sub url */
optional string SubURI = 2; /**< sub uri */
optional string SubName = 3;
optional string SubPath = 4;
optional int32 SiteId = 5; /**< 子链接site id */
optional string SubEx = 6; /**< extend */
};
//------------------------------------gss单个结果结构体:gss_res_t---------------------------------
//struct gss_res_t
//{
// string ResultURL; /**< 结果URL */
// string Display = optional(),default(""); /**< 展现结果 */
// int32_t Weight; /**< 权重 */
// int32_t Sort = optional(); /**< 插入位置 */
// int32_t SrcID = optional(); /**< id */
// int32_t TimingNeed; /**< 时效性 */
// uint32_t WiseStrategyFlag = optional(); /**< wise策略bitmap */
// int32_t Degree = optional(); /**< 需求强度 */
// int32_t ClickNeed = optional(); /**< 点击调权 */
// int32_t StrategyInfo = optional(); /**< 策略附加信息 */
// //SPEC REQ
// int32_t SpReqType = optional(); /**< 特殊请求类型,正常为0 */
// //FRO ZHIXIN USE
// string UriKey = optional(); /**< UriKey 知心卡片使用 */
// string EntityName = optional(); /**< 实体名 知心卡片使用 */
// sub_url_t SubResult[50]; /**< 50条子链接 */
// int32_t SubResNum = optional(),default(0); /**< 子链接 */
// string DisplayLog = optional(); /**< 展现日志 */
// binary DisplayData = optional(); /**< 特型展现数据 */
// uint32_t ResType = optional(); /**< 资源是否带图*/
// string Title = optional(); /**< 右侧去重名称*/
// int32_t RecoverCacheTime = optional(); /**< us容灾cache,过滤不进人容灾的资源*/
//};
message gss_res_t {
// pb for gss_res_t:
required string ResultURL = 2; /**< 结果URL */
optional string Display = 3; /**< 展现结果 */
required int32 Weight = 4; /**< 权重 */
optional int32 Sort = 5; /**< 插入位置 */
optional int32 SrcID = 6; /**< id */
required int32 TimingNeed = 7; /**< 时效性 */
optional uint32 WiseStrategyFlag = 8; /**< wise策略bitmap */
optional int32 Degree = 9; /**< 需求强度 */
optional int32 ClickNeed = 10; /**< 点击调权 */
optional int32 StrategyInfo = 11; /**< 策略附加信息 */
//SPEC REQ
optional int32 SpReqType = 12; /**< 特殊请求类型,正常为0 */
//FRO ZHIXIN USE
optional string UriKey = 13; /**< UriKey 知心卡片使用 */
optional string EntityName = 14; /**< 实体名 知心卡片使用 */
repeated sub_url_t SubResult = 15; /**< 50条子链接 */
optional int32 SubResNum = 16; /**< 子链接 */
optional string DisplayLog = 17; /**< 展现日志 */
optional bytes DisplayData = 18; /**< 特型展现数据 */
optional uint32 ResType = 19; /**< 资源是否带图*/
optional string Title = 20; /**< 右侧去重名称*/
optional int32 RecoverCacheTime = 21; /**< us容灾cache,过滤不进人容灾的资源*/
//customized result messages:
};
//------------------------------------debug_info_t---------------------------------
//struct item_t
//{
// string title;
// string content;
// int32_t parent;
//};
//struct strategy_bits_t
//{
// uint32_t bits[STRATEGY_INT_NUM];
//};
//struct debug_info_t
//{
// ///废弃, 使用idebug代替
// item_t debug_info[] = optional();
// string item_info[] = optional();
// string anchor_info[] = optional();
// ///通过ivar 发送的全部debug信息, 取代原debug_info
// binary idebug = optional();
//};
message item_t {
required string title = 1;
required string content = 2;
required int32 parent = 3;
};
message debug_info_t {
optional bytes idebug = 1;
repeated string item_info = 2;
repeated string anchor_info = 3;
///废弃, 使用idebug代替
repeated item_t debug_info = 4 [deprecated=true];
};
//------------------------------------gss_us_res_t---------------------------------
// gss返回给us结构体
//struct gss_us_res_t
//{
// int32_t ResultCode; /**< 返回状态码 */
// uint64_t QueryID; /**< query id */
// //集群合并后,加大最大返回结果包大小
// gss_res_t Result[40]; /**< 返回结果 */
// uint32_t ResultNum = range(0,40); /**< 返回结果数 */
// debug_info_t info = optional(); /**< debug info */
// int32_t bfe_cached_time = optional(); /**< cache失效时间 */
// int32_t bfe_cached_islocate = optional(); /**< 是否有地域扩展 */
// binary disp_data_url_ex = optional(); /**< 展现日志中url级别信息 */
// binary disp_data_query_ex = optional(); /**< 展现日志中query级别信息 */
//};
// pb for gss_us_res_t:
message gss_us_res_t {
required int32 ResultCode = 1; /**< 返回状态码 */
required uint64 QueryID = 2; /**< query id */
//集群合并后,加大最大返回结果包大小
repeated gss_res_t Result = 3; /**< 返回结果 */
required uint32 ResultNum = 4; /**< 返回结果数 */
optional debug_info_t info = 5; /**< debug info */
optional int32 bfe_cached_time = 6; /**< cache失效时间 */
optional int32 bfe_cached_islocate = 7; /**< 是否有地域扩展 */
optional bytes disp_data_url_ex = 8; /**< 展现日志中url级别信息 */
optional bytes disp_data_query_ex = 9; /**< 展现日志中query级别信息 */
optional string name = 20; /* response name*/
};
message Dummy {}
message RepeatedMessage {
repeated int32 ints = 1;
repeated string strings = 2;
repeated Dummy msgs = 3;
}
......@@ -43,6 +43,10 @@ cat $PATCHFILE | sed -e 's/src\/baidu\/rpc\//src\/brpc\//g' \
-e 's/<\(base\/[^>]*\)>/"\1"/g' \
-e 's/<\(bthread\/[^>]*\)>/"\1"/g' \
-e 's/<\(mcpack2pb\/[^>]*\)>/"\1"/g' \
-e 's/\<protobuf_json\>/json2pb/g' \
-e 's/src\/json_to_pb/src\/json2pb\/json_to_pb/g' \
-e 's/src\/pb_to_json/src\/json2pb\/pb_to_json/g' \
-e 's/test\/test_protobuf_json/test\/brpc_protobuf_json_unittest/g' \
-e 's/ base\// src\/base\//g' \
-e 's/ bthread\// src\/bthread\//g' \
-e 's/ bvar\// src\/bvar\//g' \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment