{"action":"created","comment":{"url":"https://api.github.com/repos/mapsme/omim/pulls/comments/211982327","pull_request_review_id":148517395,"id":211982327,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMTk4MjMyNw==","diff_hunk":"@@ -0,0 +1,428 @@\n+#include \"generator/regions_kv.hpp\"\n+\n+#include \"generator/feature_builder.hpp\"\n+#include \"generator/generate_info.hpp\"\n+#include \"generator/region_info_collector.hpp\"\n+#include \"generator/thread_pool.hpp\"\n+\n+#include \"geometry/region2d.hpp\"\n+\n+#include \"platform/platform.hpp\"\n+\n+#include \"coding/file_name_utils.hpp\"\n+\n+#include \"base/geo_object_id.hpp\"\n+\n+#include \"defines.hpp\"\n+\n+#include \"3party/jansson/myjansson.hpp\"\n+\n+#include <fstream>\n+#include <memory>\n+#include <queue>\n+#include <string>\n+#include <thread>\n+#include <unordered_set>\n+#include <vector>\n+\n+namespace\n+{\n+using namespace generator;\n+\n+struct Region\n+{\n+  static short constexpr kNoRank = -1;\n+\n+  using Point = FeatureBuilder1::PointSeq::value_type;\n+\n+  Region(FeatureBuilder1 const & fb, generator::RegionData const & rd) :\n+    m_name(fb.GetParams().name),\n+    m_region(std::move(fb.GetOuterGeometry())),\n+    m_regionData(rd),\n+    m_center(fb.GetGeometryCenter())\n+  {\n+    auto const rect = m_region.GetRect();\n+    m_area = (rect.maxX() - rect.minX()) * (rect.maxY() - rect.minY());\n+  }\n+\n+  std::string GetName(int8_t lang = StringUtf8Multilang::kDefaultCode) const\n+  {\n+    std::string s;\n+    VERIFY(m_name.GetString(lang, s) != s.empty(), ());\n+    return s;\n+  }\n+\n+  void RemoveRegionGeometry()\n+  {\n+    m_region = std::move(m2::Region<Point>());\n+  }\n+\n+  bool IsCountry() const\n+  {\n+    static int8_t const kAdmLvlCountry = 2;\n+    return m_regionData.m_adminLevel == kAdmLvlCountry;\n+  }\n+\n+  bool IsContains(Region const & smaller) const\n+  {\n+    auto const & region = smaller.m_region.Data();\n+    auto leftRigth = std::minmax_element(std::begin(region), std::end(region),\n+                                         [](const Point & l, const Point & r) { return l.x < r.x; });\n+    auto bottomTop = std::minmax_element(std::begin(region), std::end(region),\n+                                         [](const Point & l, const Point & r) { return l.y < r.y; });\n+\n+    return m_region.Contains(*leftRigth.first) &&\n+        m_region.Contains(*leftRigth.second) &&\n+        m_region.Contains(*bottomTop.first) &&\n+        m_region.Contains(*bottomTop.second);\n+  }\n+\n+  short GetRank() const\n+  {\n+    if (m_regionData.m_adminLevel >= 2 && m_regionData.m_adminLevel <= 4)\n+      return m_regionData.m_adminLevel;\n+\n+    switch (m_regionData.m_place)\n+    {\n+    case PlaceType::City: return 10;\n+    case PlaceType::Town: return 11;\n+    case PlaceType::Village: return 13;\n+    default:\n+      break;\n+    }\n+\n+    if (m_regionData.m_adminLevel >= 5 && m_regionData.m_adminLevel <= 8)\n+      return m_regionData.m_adminLevel;\n+\n+    switch (m_regionData.m_place)\n+    {\n+    case PlaceType::Suburb: return 14;\n+    case PlaceType::Neighbourhood: return 15;\n+    case PlaceType::Hamlet: return 17;\n+    case PlaceType::Locality: return 19;\n+    case PlaceType::IsolatedDwelling: return 20;\n+    default:\n+      break;\n+    }\n+\n+    return kNoRank;\n+  }\n+\n+  std::string GetLabel() const\n+  {\n+    switch (m_regionData.m_adminLevel)\n+    {\n+    case 2: return \"country\";\n+    case 4: return \"region\";\n+    default:\n+      break;\n+    }\n+\n+    switch (m_regionData.m_place)\n+    {\n+    case PlaceType::City:\n+    case PlaceType::Town:\n+    case PlaceType::Village:\n+    case PlaceType::Hamlet:\n+      return \"locality\";\n+    default:\n+      break;\n+    }\n+\n+    switch (m_regionData.m_adminLevel)\n+    {\n+    case 6: return \"subregion\";\n+    default:\n+      break;\n+    }\n+\n+    switch (m_regionData.m_place)\n+    {\n+    case PlaceType::Suburb:\n+    case PlaceType::Neighbourhood:\n+      return \"suburb\";\n+    case PlaceType::Locality:\n+    case PlaceType::IsolatedDwelling:\n+      return \"sublocality\";\n+    default:\n+      break;\n+    }\n+\n+    return \"\";\n+  }\n+\n+  StringUtf8Multilang m_name;\n+  m2::Region<Point> m_region;\n+  RegionData m_regionData;\n+  Point m_center;\n+  double m_area;\n+};\n+\n+struct Node;\n+using NodePtr = std::shared_ptr<Node>;\n+using NodeWPtr = std::weak_ptr<Node>;\n+using NodePtrList = std::vector<NodePtr>;\n+\n+struct Node\n+{\n+  Node(Region const & region) : m_region(region) {}\n+\n+  Region m_region;\n+  NodePtrList m_children;\n+  NodeWPtr m_parent;\n+};\n+\n+// This function is for debugging only and can be a collection of statistics.\n+int SizeTree(NodePtr node)\n+{\n+  if (node->m_children.empty())\n+    return 1;\n+\n+  int i = 0;\n+  for (auto const & n : node->m_children)\n+    i += SizeTree(n);\n+\n+  return i + 1;\n+}\n+\n+// This function is for debugging only and can be a collection of statistics.\n+int MaxDepth(NodePtr node)\n+{\n+  if (node->m_children.empty())\n+    return 1;\n+\n+  int i = -1;\n+  for (auto const & n : node->m_children)\n+    i = std::max(MaxDepth(n), i);\n+\n+  return i + 1;\n+}\n+\n+class JsonPolicy\n+{\n+public:\n+  std::string ToString(NodePtrList const & nodePtrList) const\n+  {\n+    if (nodePtrList.empty())\n+      return \"\";\n+\n+    const auto & main = nodePtrList[0];\n+\n+    auto geometry = my::NewJSONObject();\n+    ToJSONObject(*geometry, \"type\", \"Point\");\n+    auto coordinates = my::NewJSONArray();\n+    ToJSONArray(*coordinates, main->m_region.m_center.x);\n+    ToJSONArray(*coordinates, main->m_region.m_center.y);\n+    ToJSONObject(*geometry, \"coordinates\", coordinates);\n+\n+    auto address = my::NewJSONObject();\n+    for (auto const & p : nodePtrList)\n+      ToJSONObject(*address, p->m_region.GetLabel(), p->m_region.GetName());\n+\n+    auto properties = my::NewJSONObject();\n+    ToJSONObject(*properties, \"name\", main->m_region.GetName());\n+    ToJSONObject(*properties, \"rank\", main->m_region.GetRank());\n+    ToJSONObject(*properties, \"address\", address);\n+\n+    auto feature = my::NewJSONObject();\n+    ToJSONObject(*feature, \"type\", \"Feature\");\n+    ToJSONObject(*feature, \"geometry\", geometry);\n+    ToJSONObject(*feature, \"properties\", properties);\n+\n+    return json_dumps(feature.release(), JSON_COMPACT);\n+  }\n+};\n+\n+template<typename ToStringPolicy>\n+class RegionKvBuilder : public ToStringPolicy\n+{\n+public:\n+  using Regions = std::vector<Region>;\n+  using StringList = std::vector<std::string>;\n+  using CountryTrees = std::multimap<std::string, NodePtr>;\n+\n+  explicit RegionKvBuilder(Regions && pregions)\n+  {\n+    Regions regions(std::move(pregions));\n+    std::copy_if(std::begin(regions), std::end(regions), std::back_inserter(m_countries),\n+                 [](Region const & r){ return r.IsCountry(); });\n+    auto const it = std::remove_if(std::begin(regions), std::end(regions),\n+                                   [](Region const & r){ return r.IsCountry(); });\n+    regions.erase(it, std::end(regions));\n+\n+    MakeCountryTrees(regions);\n+  }\n+\n+  const Regions & GetCountries() const { return m_countries; }\n+\n+  StringList GetCountryNames() const\n+  {\n+    StringList result;\n+    std::unordered_set<std::string> set;\n+    for (auto const & c : GetCountries())\n+    {\n+      auto const name = c.GetName();\n+      if (set.count(name))\n+        continue;\n+\n+      set.insert(name);\n+      result.emplace_back(std::move(name));\n+    }\n+\n+    return result;\n+  }\n+\n+  const CountryTrees & GetCountryTrees() const { return m_cuntryTrees; }\n+\n+  StringList ToStrings(NodePtr tree) const\n+  {\n+    StringList result;\n+    std::queue<NodePtr> queue;\n+    queue.push(tree);\n+    while (!queue.empty())\n+    {\n+      const auto el = queue.front();\n+      queue.pop();\n+      NodePtrList nodes;\n+      auto current = el;\n+      while (current)\n+      {\n+        nodes.push_back(current);\n+        current = current->m_parent.lock();\n+      }\n+\n+      result.emplace_back(ToStringPolicy::ToString(nodes));\n+      for (auto const & n : el->m_children)\n+        queue.push(n);\n+    }\n+\n+    return result;\n+  }\n+\n+private:\n+  static NodePtr BuildCountryRegionTree(Region const & country, Regions const & allRegions)\n+  {\n+    Regions regionsInCountry;\n+    auto const rectCountry = country.m_region.GetRect();\n+    std::copy_if(std::begin(allRegions), std::end(allRegions), std::back_inserter(regionsInCountry),\n+                 [&country, &rectCountry] (const Region & r)\n+    {\n+      auto const rect = r.m_region.GetRect();\n+      return rectCountry.IsRectInside(rect) && !r.IsCountry();\n+    });\n+\n+    regionsInCountry.emplace_back(country);\n+    std::sort(std::begin(regionsInCountry), std::end(regionsInCountry),\n+              [](const Region & r, const Region & l) { return r.m_area > l.m_area; });\n+\n+    std::vector<NodePtr> nodes;\n+    nodes.reserve(regionsInCountry.size());\n+    std::transform(std::begin(regionsInCountry), std::end(regionsInCountry),std::back_inserter(nodes),\n+                   [](const Region & r) { return std::make_shared<Node>(r); });\n+\n+    while (nodes.size() > 1)\n+    {\n+      auto itFirstNode = std::rbegin(nodes);\n+      auto & firstRegion = (*itFirstNode)->m_region;\n+      auto const & rectFirst = firstRegion.m_region.GetRect();\n+      auto itCurr = itFirstNode + 1;\n+      for (; itCurr != std::rend(nodes); ++itCurr)\n+      {\n+        auto const & currRegion = (*itCurr)->m_region;\n+        auto const & rectCurr = currRegion.m_region.GetRect();\n+        if (rectCurr.IsRectInside(rectFirst) && currRegion.IsContains(firstRegion))\n+        {\n+          (*itFirstNode)->m_parent = *itCurr;\n+          (*itCurr)->m_children.push_back(*itFirstNode);\n+          firstRegion.RemoveRegionGeometry();\n+          nodes.pop_back();\n+          break;\n+        }\n+      }\n+\n+      if (itCurr == std::rend(nodes))\n+        nodes.pop_back();\n+    }\n+\n+    return nodes.empty() ? std::shared_ptr<Node>() : nodes[0];\n+  }\n+\n+  void MakeCountryTrees(Regions const & regions)\n+  {\n+    std::vector<std::future<NodePtr>> results;\n+    {\n+      auto const cpuCount = std::thread::hardware_concurrency();\n+      ASSERT_GREATER(cpuCount, 0, ());\n+      ThreadPool threadPool(cpuCount);\n+      for (auto const & country : GetCountries())\n+      {\n+        auto f = threadPool.enqueue(&RegionKvBuilder::BuildCountryRegionTree, country, regions);\n+        results.emplace_back(std::move(f));\n+      }\n+    }\n+\n+    for (auto & r : results)\n+    {\n+      auto const tree = r.get();\n+      m_cuntryTrees.insert({tree->m_region.GetName(), tree});\n+    }\n+  }\n+\n+  CountryTrees m_cuntryTrees;\n+  Regions m_countries;\n+};\n+\n+using RegionKvBuilderJson = RegionKvBuilder<JsonPolicy>;\n+}  // namespace\n+\n+namespace generator\n+{\n+bool GenerateRegionsKv(feature::GenerateInfo const & genInfo)\n+{ \n+  auto const collectorFileName = genInfo.GetTmpFileName(genInfo.m_fileName,\n+                                                        RegionInfoCollector::kDefaultExt);\n+  RegionInfoCollector regionsInfoCollector(collectorFileName);\n+  RegionKvBuilderJson::Regions regions;\n+\n+  auto const tmpMwmFileName = genInfo.GetTmpFileName(genInfo.m_fileName);\n+  auto callback = [&regions, &regionsInfoCollector](const FeatureBuilder1 & fb, uint64_t)\n+  {\n+    if (!fb.IsArea() || !fb.IsGeometryClosed())\n+      return;\n+\n+    auto const id = fb.GetLastOsmId().GetSerialId();","path":"generator/regions_kv.cpp","position":398,"original_position":393,"commit_id":"ca1e58ad7fa785288afade307f9a09561e967871","original_commit_id":"270a48364d50069e9a22fcf829d5a6d20b1ca6bf","user":{"login":"maksimandrianov","id":12376740,"node_id":"MDQ6VXNlcjEyMzc2NzQw","avatar_url":"https://avatars3.githubusercontent.com/u/12376740?v=4","gravatar_id":"","url":"https://api.github.com/users/maksimandrianov","html_url":"https://github.com/maksimandrianov","followers_url":"https://api.github.com/users/maksimandrianov/followers","following_url":"https://api.github.com/users/maksimandrianov/following{/other_user}","gists_url":"https://api.github.com/users/maksimandrianov/gists{/gist_id}","starred_url":"https://api.github.com/users/maksimandrianov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maksimandrianov/subscriptions","organizations_url":"https://api.github.com/users/maksimandrianov/orgs","repos_url":"https://api.github.com/users/maksimandrianov/repos","events_url":"https://api.github.com/users/maksimandrianov/events{/privacy}","received_events_url":"https://api.github.com/users/maksimandrianov/received_events","type":"User","site_admin":false},"body":"++ изменил","created_at":"2018-08-22T14:45:05Z","updated_at":"2018-08-22T14:45:05Z","html_url":"https://github.com/mapsme/omim/pull/9340#discussion_r211982327","pull_request_url":"https://api.github.com/repos/mapsme/omim/pulls/9340","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/mapsme/omim/pulls/comments/211982327"},"html":{"href":"https://github.com/mapsme/omim/pull/9340#discussion_r211982327"},"pull_request":{"href":"https://api.github.com/repos/mapsme/omim/pulls/9340"}},"in_reply_to_id":211688611},"pull_request":{"url":"https://api.github.com/repos/mapsme/omim/pulls/9340","id":209854698,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA5ODU0Njk4","html_url":"https://github.com/mapsme/omim/pull/9340","diff_url":"https://github.com/mapsme/omim/pull/9340.diff","patch_url":"https://github.com/mapsme/omim/pull/9340.patch","issue_url":"https://api.github.com/repos/mapsme/omim/issues/9340","number":9340,"state":"open","locked":false,"title":"[generator] Region kv","user":{"login":"maksimandrianov","id":12376740,"node_id":"MDQ6VXNlcjEyMzc2NzQw","avatar_url":"https://avatars3.githubusercontent.com/u/12376740?v=4","gravatar_id":"","url":"https://api.github.com/users/maksimandrianov","html_url":"https://github.com/maksimandrianov","followers_url":"https://api.github.com/users/maksimandrianov/followers","following_url":"https://api.github.com/users/maksimandrianov/following{/other_user}","gists_url":"https://api.github.com/users/maksimandrianov/gists{/gist_id}","starred_url":"https://api.github.com/users/maksimandrianov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maksimandrianov/subscriptions","organizations_url":"https://api.github.com/users/maksimandrianov/orgs","repos_url":"https://api.github.com/users/maksimandrianov/repos","events_url":"https://api.github.com/users/maksimandrianov/events{/privacy}","received_events_url":"https://api.github.com/users/maksimandrianov/received_events","type":"User","site_admin":false},"body":"Пример запуска может быть таким.\r\n--user_resource_path=/home/andrianov/Projects/omim/data --intermediate_data_path=/home/andrianov/Projects/ISLANDS/intermediate_data --node_storage=map --osm_file_type=o5m --osm_file_name=/home/andrianov/Projects/omim/tools/unix/islands.o5m --output=regions_islands --generate_region_features=true --generate_regions_kv=true\r\nРаботает только вместе с [generate_region_features].\r\nПо итогу работы создаст [output].jsonl в  [intermediate_data_path]\r\n\r\nПостроение дерева для страны со всеми вложенными регионами - O(n^2).\r\n\r\nТак же был добавлен thread_pool с просторов github. Он очень простой, классный и использует возможности C++11, в отличии от нашего старого.\r\n\r\nПример результата работы на островах - прилагается [regions_islands.jsonl.gz](https://github.com/mapsme/omim/files/2306801/regions_islands.jsonl.gz).","created_at":"2018-08-21T14:53:11Z","updated_at":"2018-08-22T14:45:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"33c9a61d4fac1dd59a83997884bb75063b0bc427","assignee":null,"assignees":[],"requested_reviewers":[{"login":"syershov","id":14223965,"node_id":"MDQ6VXNlcjE0MjIzOTY1","avatar_url":"https://avatars3.githubusercontent.com/u/14223965?v=4","gravatar_id":"","url":"https://api.github.com/users/syershov","html_url":"https://github.com/syershov","followers_url":"https://api.github.com/users/syershov/followers","following_url":"https://api.github.com/users/syershov/following{/other_user}","gists_url":"https://api.github.com/users/syershov/gists{/gist_id}","starred_url":"https://api.github.com/users/syershov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/syershov/subscriptions","organizations_url":"https://api.github.com/users/syershov/orgs","repos_url":"https://api.github.com/users/syershov/repos","events_url":"https://api.github.com/users/syershov/events{/privacy}","received_events_url":"https://api.github.com/users/syershov/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/mapsme/omim/pulls/9340/commits","review_comments_url":"https://api.github.com/repos/mapsme/omim/pulls/9340/comments","review_comment_url":"https://api.github.com/repos/mapsme/omim/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mapsme/omim/issues/9340/comments","statuses_url":"https://api.github.com/repos/mapsme/omim/statuses/ca1e58ad7fa785288afade307f9a09561e967871","head":{"label":"maksimandrianov:region_kv","ref":"region_kv","sha":"ca1e58ad7fa785288afade307f9a09561e967871","user":{"login":"maksimandrianov","id":12376740,"node_id":"MDQ6VXNlcjEyMzc2NzQw","avatar_url":"https://avatars3.githubusercontent.com/u/12376740?v=4","gravatar_id":"","url":"https://api.github.com/users/maksimandrianov","html_url":"https://github.com/maksimandrianov","followers_url":"https://api.github.com/users/maksimandrianov/followers","following_url":"https://api.github.com/users/maksimandrianov/following{/other_user}","gists_url":"https://api.github.com/users/maksimandrianov/gists{/gist_id}","starred_url":"https://api.github.com/users/maksimandrianov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maksimandrianov/subscriptions","organizations_url":"https://api.github.com/users/maksimandrianov/orgs","repos_url":"https://api.github.com/users/maksimandrianov/repos","events_url":"https://api.github.com/users/maksimandrianov/events{/privacy}","received_events_url":"https://api.github.com/users/maksimandrianov/received_events","type":"User","site_admin":false},"repo":{"id":133388788,"node_id":"MDEwOlJlcG9zaXRvcnkxMzMzODg3ODg=","name":"omim","full_name":"maksimandrianov/omim","owner":{"login":"maksimandrianov","id":12376740,"node_id":"MDQ6VXNlcjEyMzc2NzQw","avatar_url":"https://avatars3.githubusercontent.com/u/12376740?v=4","gravatar_id":"","url":"https://api.github.com/users/maksimandrianov","html_url":"https://github.com/maksimandrianov","followers_url":"https://api.github.com/users/maksimandrianov/followers","following_url":"https://api.github.com/users/maksimandrianov/following{/other_user}","gists_url":"https://api.github.com/users/maksimandrianov/gists{/gist_id}","starred_url":"https://api.github.com/users/maksimandrianov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maksimandrianov/subscriptions","organizations_url":"https://api.github.com/users/maksimandrianov/orgs","repos_url":"https://api.github.com/users/maksimandrianov/repos","events_url":"https://api.github.com/users/maksimandrianov/events{/privacy}","received_events_url":"https://api.github.com/users/maksimandrianov/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/maksimandrianov/omim","description":"🗺️ MAPS.ME — Offline OpenStreetMap maps for iOS and Android","fork":true,"url":"https://api.github.com/repos/maksimandrianov/omim","forks_url":"https://api.github.com/repos/maksimandrianov/omim/forks","keys_url":"https://api.github.com/repos/maksimandrianov/omim/keys{/key_id}","collaborators_url":"https://api.github.com/repos/maksimandrianov/omim/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/maksimandrianov/omim/teams","hooks_url":"https://api.github.com/repos/maksimandrianov/omim/hooks","issue_events_url":"https://api.github.com/repos/maksimandrianov/omim/issues/events{/number}","events_url":"https://api.github.com/repos/maksimandrianov/omim/events","assignees_url":"https://api.github.com/repos/maksimandrianov/omim/assignees{/user}","branches_url":"https://api.github.com/repos/maksimandrianov/omim/branches{/branch}","tags_url":"https://api.github.com/repos/maksimandrianov/omim/tags","blobs_url":"https://api.github.com/repos/maksimandrianov/omim/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/maksimandrianov/omim/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/maksimandrianov/omim/git/refs{/sha}","trees_url":"https://api.github.com/repos/maksimandrianov/omim/git/trees{/sha}","statuses_url":"https://api.github.com/repos/maksimandrianov/omim/statuses/{sha}","languages_url":"https://api.github.com/repos/maksimandrianov/omim/languages","stargazers_url":"https://api.github.com/repos/maksimandrianov/omim/stargazers","contributors_url":"https://api.github.com/repos/maksimandrianov/omim/contributors","subscribers_url":"https://api.github.com/repos/maksimandrianov/omim/subscribers","subscription_url":"https://api.github.com/repos/maksimandrianov/omim/subscription","commits_url":"https://api.github.com/repos/maksimandrianov/omim/commits{/sha}","git_commits_url":"https://api.github.com/repos/maksimandrianov/omim/git/commits{/sha}","comments_url":"https://api.github.com/repos/maksimandrianov/omim/comments{/number}","issue_comment_url":"https://api.github.com/repos/maksimandrianov/omim/issues/comments{/number}","contents_url":"https://api.github.com/repos/maksimandrianov/omim/contents/{+path}","compare_url":"https://api.github.com/repos/maksimandrianov/omim/compare/{base}...{head}","merges_url":"https://api.github.com/repos/maksimandrianov/omim/merges","archive_url":"https://api.github.com/repos/maksimandrianov/omim/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/maksimandrianov/omim/downloads","issues_url":"https://api.github.com/repos/maksimandrianov/omim/issues{/number}","pulls_url":"https://api.github.com/repos/maksimandrianov/omim/pulls{/number}","milestones_url":"https://api.github.com/repos/maksimandrianov/omim/milestones{/number}","notifications_url":"https://api.github.com/repos/maksimandrianov/omim/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/maksimandrianov/omim/labels{/name}","releases_url":"https://api.github.com/repos/maksimandrianov/omim/releases{/id}","deployments_url":"https://api.github.com/repos/maksimandrianov/omim/deployments","created_at":"2018-05-14T16:11:26Z","updated_at":"2018-08-21T14:07:39Z","pushed_at":"2018-08-22T10:56:51Z","git_url":"git://github.com/maksimandrianov/omim.git","ssh_url":"git@github.com:maksimandrianov/omim.git","clone_url":"https://github.com/maksimandrianov/omim.git","svn_url":"https://github.com/maksimandrianov/omim","homepage":"","size":4022176,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mapsme:master","ref":"master","sha":"85e7a4e9f4ff046a87c0a39022859a0984101275","user":{"login":"mapsme","id":14185141,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTg1MTQx","avatar_url":"https://avatars1.githubusercontent.com/u/14185141?v=4","gravatar_id":"","url":"https://api.github.com/users/mapsme","html_url":"https://github.com/mapsme","followers_url":"https://api.github.com/users/mapsme/followers","following_url":"https://api.github.com/users/mapsme/following{/other_user}","gists_url":"https://api.github.com/users/mapsme/gists{/gist_id}","starred_url":"https://api.github.com/users/mapsme/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapsme/subscriptions","organizations_url":"https://api.github.com/users/mapsme/orgs","repos_url":"https://api.github.com/users/mapsme/repos","events_url":"https://api.github.com/users/mapsme/events{/privacy}","received_events_url":"https://api.github.com/users/mapsme/received_events","type":"Organization","site_admin":false},"repo":{"id":42798033,"node_id":"MDEwOlJlcG9zaXRvcnk0Mjc5ODAzMw==","name":"omim","full_name":"mapsme/omim","owner":{"login":"mapsme","id":14185141,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTg1MTQx","avatar_url":"https://avatars1.githubusercontent.com/u/14185141?v=4","gravatar_id":"","url":"https://api.github.com/users/mapsme","html_url":"https://github.com/mapsme","followers_url":"https://api.github.com/users/mapsme/followers","following_url":"https://api.github.com/users/mapsme/following{/other_user}","gists_url":"https://api.github.com/users/mapsme/gists{/gist_id}","starred_url":"https://api.github.com/users/mapsme/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapsme/subscriptions","organizations_url":"https://api.github.com/users/mapsme/orgs","repos_url":"https://api.github.com/users/mapsme/repos","events_url":"https://api.github.com/users/mapsme/events{/privacy}","received_events_url":"https://api.github.com/users/mapsme/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mapsme/omim","description":"🗺️ MAPS.ME — Offline OpenStreetMap maps for iOS and Android","fork":false,"url":"https://api.github.com/repos/mapsme/omim","forks_url":"https://api.github.com/repos/mapsme/omim/forks","keys_url":"https://api.github.com/repos/mapsme/omim/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mapsme/omim/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mapsme/omim/teams","hooks_url":"https://api.github.com/repos/mapsme/omim/hooks","issue_events_url":"https://api.github.com/repos/mapsme/omim/issues/events{/number}","events_url":"https://api.github.com/repos/mapsme/omim/events","assignees_url":"https://api.github.com/repos/mapsme/omim/assignees{/user}","branches_url":"https://api.github.com/repos/mapsme/omim/branches{/branch}","tags_url":"https://api.github.com/repos/mapsme/omim/tags","blobs_url":"https://api.github.com/repos/mapsme/omim/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mapsme/omim/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mapsme/omim/git/refs{/sha}","trees_url":"https://api.github.com/repos/mapsme/omim/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mapsme/omim/statuses/{sha}","languages_url":"https://api.github.com/repos/mapsme/omim/languages","stargazers_url":"https://api.github.com/repos/mapsme/omim/stargazers","contributors_url":"https://api.github.com/repos/mapsme/omim/contributors","subscribers_url":"https://api.github.com/repos/mapsme/omim/subscribers","subscription_url":"https://api.github.com/repos/mapsme/omim/subscription","commits_url":"https://api.github.com/repos/mapsme/omim/commits{/sha}","git_commits_url":"https://api.github.com/repos/mapsme/omim/git/commits{/sha}","comments_url":"https://api.github.com/repos/mapsme/omim/comments{/number}","issue_comment_url":"https://api.github.com/repos/mapsme/omim/issues/comments{/number}","contents_url":"https://api.github.com/repos/mapsme/omim/contents/{+path}","compare_url":"https://api.github.com/repos/mapsme/omim/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mapsme/omim/merges","archive_url":"https://api.github.com/repos/mapsme/omim/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mapsme/omim/downloads","issues_url":"https://api.github.com/repos/mapsme/omim/issues{/number}","pulls_url":"https://api.github.com/repos/mapsme/omim/pulls{/number}","milestones_url":"https://api.github.com/repos/mapsme/omim/milestones{/number}","notifications_url":"https://api.github.com/repos/mapsme/omim/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mapsme/omim/labels{/name}","releases_url":"https://api.github.com/repos/mapsme/omim/releases{/id}","deployments_url":"https://api.github.com/repos/mapsme/omim/deployments","created_at":"2015-09-20T02:57:13Z","updated_at":"2018-08-22T13:49:01Z","pushed_at":"2018-08-22T13:48:48Z","git_url":"git://github.com/mapsme/omim.git","ssh_url":"git@github.com:mapsme/omim.git","clone_url":"https://github.com/mapsme/omim.git","svn_url":"https://github.com/mapsme/omim","homepage":"","size":4054198,"stargazers_count":2752,"watchers_count":2752,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":597,"mirror_url":null,"archived":false,"open_issues_count":725,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":597,"open_issues":725,"watchers":2752,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mapsme/omim/pulls/9340"},"html":{"href":"https://github.com/mapsme/omim/pull/9340"},"issue":{"href":"https://api.github.com/repos/mapsme/omim/issues/9340"},"comments":{"href":"https://api.github.com/repos/mapsme/omim/issues/9340/comments"},"review_comments":{"href":"https://api.github.com/repos/mapsme/omim/pulls/9340/comments"},"review_comment":{"href":"https://api.github.com/repos/mapsme/omim/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mapsme/omim/pulls/9340/commits"},"statuses":{"href":"https://api.github.com/repos/mapsme/omim/statuses/ca1e58ad7fa785288afade307f9a09561e967871"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"maksimandrianov"}}