2929#include < rapidjson/writer.h>
3030
3131namespace {
32- void WriteSubquadsToJson (rapidjson::Document& doc,
33- const olp::geo::TileKey& root_tile,
34- const std::vector<std::uint16_t >& sub_quads,
35- rapidjson::Document::AllocatorType& allocator) {
32+
33+ void WriteSubquadsToJson (
34+ rapidjson::Document& doc, const olp::geo::TileKey& root_tile,
35+ const std::map<std::uint64_t , mockserver::TileMetadata>& sub_quads,
36+ rapidjson::Document::AllocatorType& allocator) {
3637 rapidjson::Value sub_quads_value;
3738 sub_quads_value.SetArray ();
3839 for (auto quad : sub_quads) {
39- const auto partition = root_tile.AddedSubkey64 (quad).ToHereTile ();
40- const auto data_handle =
41- mockserver::ReadDefaultResponses::GenerateDataHandle (partition) ;
40+ const auto partition = root_tile.AddedSubkey64 (quad. first ).ToHereTile ();
41+ const auto & data_handle = quad. second . data_handle ;
42+ const auto version = quad. second . version ;
4243
4344 rapidjson::Value item_value;
4445 item_value.SetObject ();
45- olp::serializer::serialize (" subQuadKey" , std::to_string (quad), item_value ,
46- allocator);
47- olp::serializer::serialize (" version" , 0 , item_value, allocator);
46+ olp::serializer::serialize (" subQuadKey" , std::to_string (quad. first ) ,
47+ item_value, allocator);
48+ olp::serializer::serialize (" version" , version , item_value, allocator);
4849 olp::serializer::serialize (" dataHandle" , data_handle, item_value,
4950 allocator);
50- olp::serializer::serialize (" dataSize" , 100 , item_value, allocator);
5151 sub_quads_value.PushBack (std::move (item_value), allocator);
5252 }
5353 doc.AddMember (" subQuads" , std::move (sub_quads_value), allocator);
5454}
5555
56- void WriteParentquadsToJson (rapidjson::Document& doc,
57- const std::vector<std::uint64_t >& parent_quads,
58- rapidjson::Document::AllocatorType& allocator) {
56+ void WriteParentquadsToJson (
57+ rapidjson::Document& doc,
58+ const std::map<std::uint64_t , mockserver::TileMetadata>& parent_quads,
59+ rapidjson::Document::AllocatorType& allocator) {
5960 rapidjson::Value parent_quads_value;
6061 parent_quads_value.SetArray ();
6162 for (auto parent : parent_quads) {
62- const auto partition = std::to_string (parent);
63- const auto data_handle =
64- mockserver::ReadDefaultResponses::GenerateDataHandle (partition) ;
63+ const auto partition = std::to_string (parent. first );
64+ const auto version = parent. second . version ;
65+ const auto & data_handle = parent. second . data_handle ;
6566
6667 rapidjson::Value item_value;
6768 item_value.SetObject ();
68- olp::serializer::serialize (" partition" , std::to_string (parent), item_value,
69- allocator);
70- olp::serializer::serialize (" version" , 0 , item_value, allocator);
69+ olp::serializer::serialize (" partition" , partition, item_value, allocator);
70+ olp::serializer::serialize (" version" , version, item_value, allocator);
7171 olp::serializer::serialize (" dataHandle" , data_handle, item_value,
7272 allocator);
7373 olp::serializer::serialize (" dataSize" , 100 , item_value, allocator);
7474 parent_quads_value.PushBack (std::move (item_value), allocator);
7575 }
7676 doc.AddMember (" parentQuads" , std::move (parent_quads_value), allocator);
7777}
78+
79+ std::string GenerateRandomString (size_t length) {
80+ std::string letters =
81+ " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ;
82+ std::random_device device;
83+ std::mt19937 generator (device ());
84+ std::uniform_int_distribution<unsigned int > dis (0u , letters.length () - 1 );
85+
86+ std::string result;
87+ result.resize (length);
88+ for (auto i = 0u ; i < length; ++i) {
89+ result[i] += letters[dis (generator)];
90+ }
91+
92+ return result;
93+ }
94+
95+ void FillSubQuads (std::int32_t depth, std::vector<std::uint16_t >& sub_quads_) {
96+ const auto sub_tile = olp::geo::TileKey::FromRowColumnLevel (0 , 0 , depth);
97+ const auto start_level_id = sub_tile.ToQuadKey64 ();
98+ const auto tiles_count = olp::geo::QuadKey64Helper::ChildrenAtLevel (depth);
99+
100+ std::vector<std::uint64_t > layer_ids (tiles_count);
101+ std::iota (layer_ids.begin (), layer_ids.end (), start_level_id);
102+ sub_quads_.insert (sub_quads_.end (), layer_ids.begin (), layer_ids.end ());
103+ }
104+
78105} // namespace
79106
80107namespace mockserver {
81108
109+ std::string ReadDefaultResponses::GenerateData (size_t length) {
110+ return GenerateRandomString (length);
111+ }
112+
82113std::string ReadDefaultResponses::GenerateQuadTreeResponse (
83114 olp::geo::TileKey root_tile, std::uint32_t depth,
84115 const std::vector<std::uint32_t >& available_levels) {
85- std::vector <std::uint16_t > sub_quads;
86- std::vector <std::uint64_t > parent_quads;
116+ std::map <std::uint64_t , TileMetadata > sub_quads;
117+ std::map <std::uint64_t , TileMetadata > parent_quads;
87118
88119 // generate data
89120 for (auto level : available_levels) {
90121 if (level < root_tile.Level ()) {
91- auto key = root_tile.ChangedLevelTo (level);
92- parent_quads. push_back ( key. ToQuadKey64 ()) ;
122+ auto key = root_tile.ChangedLevelTo (level). ToQuadKey64 () ;
123+ parent_quads[ key] = { GenerateDataHandle ( std::to_string (key)), 0 } ;
93124 } else {
94125 const auto level_depth = level - root_tile.Level ();
95126 if (level_depth > depth) {
96127 continue ;
97128 }
98129
99- const auto sub_tile =
100- olp::geo::TileKey::FromRowColumnLevel (0 , 0 , level_depth);
101- const auto start_level_id = sub_tile.ToQuadKey64 ();
102- const auto tiles_count =
103- olp::geo::QuadKey64Helper::ChildrenAtLevel (level_depth);
130+ std::vector<std::uint16_t > sub_quads_vector;
131+ FillSubQuads (level_depth, sub_quads_vector);
104132
105- std::vector<std:: uint64_t > layer_ids (tiles_count);
106- std::iota (layer_ids. begin (), layer_ids. end ( ), start_level_id) ;
107- sub_quads. insert (sub_quads. end (), layer_ids. begin (), layer_ids. end ());
133+ for ( const auto & sub_quad : sub_quads_vector) {
134+ sub_quads[sub_quad] = { GenerateDataHandle ( std::to_string (sub_quad) ), 0 } ;
135+ }
108136 }
109137 }
110138
@@ -120,4 +148,89 @@ std::string ReadDefaultResponses::GenerateQuadTreeResponse(
120148 return buffer.GetString ();
121149}
122150
151+ QuadTreeBuilder::QuadTreeBuilder (olp::geo::TileKey root_tile,
152+ boost::optional<int32_t > version)
153+ : root_tile_(root_tile), base_version_(version) {}
154+
155+ QuadTreeBuilder& QuadTreeBuilder::WithParent (olp::geo::TileKey parent,
156+ std::string datahandle,
157+ boost::optional<int32_t > version) {
158+ assert (root_tile_.IsChildOf (parent));
159+
160+ // Make sure to set version when the base_version is set
161+ if (version != boost::none) {
162+ assert (base_version_ != boost::none);
163+ } else if (base_version_) {
164+ version = base_version_;
165+ }
166+
167+ parent_quads_[parent.ToQuadKey64 ()] = {datahandle, version};
168+
169+ return *this ;
170+ }
171+
172+ QuadTreeBuilder& QuadTreeBuilder::FillParents () {
173+ auto key = root_tile_.Parent ();
174+ while (key.IsValid ()) {
175+ auto quad_key = key.ToQuadKey64 ();
176+ if (parent_quads_.find (quad_key) == parent_quads_.end ()) {
177+ parent_quads_[quad_key] = {GenerateRandomString (32 ), base_version_};
178+ }
179+ }
180+ return *this ;
181+ }
182+
183+ QuadTreeBuilder& QuadTreeBuilder::WithSubQuad (
184+ olp::geo::TileKey tile, std::string datahandle,
185+ boost::optional<int32_t > version) {
186+ assert (tile.IsChildOf (root_tile_) || tile == root_tile_);
187+ assert ((tile.Level () - root_tile_.Level ()) <= 4 );
188+ if (version != boost::none) {
189+ assert (base_version_ != boost::none);
190+ }
191+
192+ auto origin = root_tile_.ChangedLevelTo (tile.Level ());
193+ auto sub_quad =
194+ olp::geo::TileKey::FromRowColumnLevel (tile.Row () - origin.Row (),
195+ tile.Column () - origin.Column (),
196+ tile.Level () - root_tile_.Level ())
197+ .ToQuadKey64 ();
198+
199+ sub_quads_[sub_quad] = {datahandle, version};
200+
201+ return *this ;
202+ }
203+
204+ QuadTreeBuilder& QuadTreeBuilder::FillSubquads (uint32_t depth) {
205+ assert (depth <= 4 );
206+
207+ std::vector<std::uint16_t > sub_quads;
208+ for (uint32_t i = 0 ; i <= depth; i++) {
209+ FillSubQuads (i, sub_quads);
210+ }
211+
212+ for (const auto & sub_quad : sub_quads) {
213+ if (sub_quads_.find (sub_quad) == sub_quads_.end ()) {
214+ sub_quads_[sub_quad] = {GenerateRandomString (32 ), base_version_};
215+ }
216+ }
217+
218+ return *this ;
219+ }
220+
221+ std::string QuadTreeBuilder::BuildJson () const {
222+ rapidjson::Document doc;
223+ auto & allocator = doc.GetAllocator ();
224+ doc.SetObject ();
225+ WriteSubquadsToJson (doc, root_tile_, sub_quads_, allocator);
226+ WriteParentquadsToJson (doc, parent_quads_, allocator);
227+
228+ rapidjson::StringBuffer buffer;
229+ rapidjson::Writer<rapidjson::StringBuffer> writer (buffer);
230+ doc.Accept (writer);
231+ return buffer.GetString ();
232+ }
233+
234+ olp::geo::TileKey QuadTreeBuilder::Root () const { return root_tile_; }
235+
123236} // namespace mockserver
0 commit comments