Browse Source

WIP: implement a city as replacement for a region

this uses bragi as source and not our postgis database. It fetches a
city and then takes the centre and fetches 20 places nearest to that.
tags/0.3.6^2
Bèr Kessels 2 months ago
parent
commit
dcc0a3c25e
35 changed files with 969 additions and 532 deletions
  1. 16
    5
      app/models/base.rb
  2. 0
    39
      app/models/base_collection.rb
  3. 41
    0
      app/models/city.rb
  4. 15
    6
      app/models/place.rb
  5. 0
    30
      app/models/place_index.rb
  6. 0
    23
      app/models/region.rb
  7. 17
    6
      app/models/search_result.rb
  8. 77
    0
      app/projections/city_query.rb
  9. 1
    2
      app/projections/place_query.rb
  10. 0
    45
      app/projections/region_query.rb
  11. 1
    1
      app/projections/search_query.rb
  12. 1
    1
      app/views/layout.erb
  13. 13
    8
      app/views/region.erb
  14. 1
    1
      app/views/search.erb
  15. 1
    1
      lib/app.rb
  16. 1
    0
      test/fixtures/input/region_nijmegen.json
  17. 37
    0
      test/fixtures/vcr_cassettes/bragi_jan_de_groot.yml
  18. 63
    0
      test/fixtures/vcr_cassettes/city_arnhem.yml
  19. 62
    0
      test/fixtures/vcr_cassettes/city_den_bosch.yml
  20. 64
    0
      test/fixtures/vcr_cassettes/city_eindhoven.yml
  21. 63
    0
      test/fixtures/vcr_cassettes/city_nijmegen.yml
  22. 64
    0
      test/fixtures/vcr_cassettes/city_zuidwolde.yml
  23. 198
    0
      test/fixtures/vcr_cassettes/city_zuidwolde_drenthe.yml
  24. 64
    0
      test/fixtures/vcr_cassettes/city_zuidwolde_groningen.yml
  25. 55
    77
      test/integration/web/view_regions_test.rb
  26. 0
    48
      test/models/base_collection_test.rb
  27. 2
    2
      test/models/base_test.rb
  28. 47
    0
      test/models/city_test.rb
  29. 0
    27
      test/models/place_index_test.rb
  30. 12
    9
      test/models/place_test.rb
  31. 0
    27
      test/models/region_test.rb
  32. 8
    8
      test/models/search_result_test.rb
  33. 45
    0
      test/projections/city_query_test.rb
  34. 0
    81
      test/projections/place_query_test.rb
  35. 0
    85
      test/projections/region_query_test.rb

+ 16
- 5
app/models/base.rb View File

@@ -5,9 +5,15 @@ module Hours
##
# Base model that can read from a query database
class Base
attr_accessor :error
attr_accessor :error, :geometry
NULL_ISLAND = GeoRuby::SimpleFeatures::Point.from_xy(0, 0)

def initialize(attributes = {}, ignore_undefined_attributes = false)
def initialize(
attributes: {},
geometry: NULL_ISLAND,
ignore_undefined_attributes: false
)
@geometry = geometry
attributes.each do |key, value|
setter = "#{key}="
send(setter, value)
@@ -17,20 +23,25 @@ module Hours
end

def self.from_geojson_feature(feature)
attrs = feature.properties.fetch('geocoding', {}) || {}
attrs = feature&.properties&.fetch('geocoding', {}) || {}
geometry = feature&.geometry || NULL_ISLAND
tags = attrs.fetch('properties', []) || []

# Turn # [{ key => 'name', value => 'someval' }] into
# { 'name' => someval }
extra_props = Hash[tags.map { |pair| [pair['key'], pair['value']] }]

new(extra_props.merge(attrs), true)
new(
attributes: extra_props.merge(attrs),
geometry: geometry,
ignore_undefined_attributes: true
)
end

protected

def null_island
GeoRuby::SimpleFeatures::Point.from_xy(0, 0)
NULL_ISLAND
end
end
end

+ 0
- 39
app/models/base_collection.rb View File

@@ -1,39 +0,0 @@
# frozen_string_literal: true

module Hours
module Models
##
# Base model that holds a list of other models
class BaseCollection < Delegator
include Enumerable

attr_accessor :paginator

def __getobj__
@dataset
end

def initialize(dataset, paginator = nil)
@dataset = dataset
@paginator = paginator
end

def to_a
@dataset.map { |row| self.class::ITEM_CLASS.new(row) }
end

def each
@dataset.each do |row|
case row
when NilClass
yield self.class::NULLITEM_CLASS.new
when Hash
yield self.class::ITEM_CLASS.new(row)
when RGeo::GeoJSON::Feature
yield self.class::ITEM_CLASS.from_geojson_feature(row)
end
end
end
end
end
end

+ 41
- 0
app/models/city.rb View File

@@ -0,0 +1,41 @@
# frozen_string_literal: true

require 'babosa'

require_relative 'base.rb'

module Hours
module Models
##
# City is a collection of Places belonging to one area.
# It is, therefore, a decorator for a list of places.
class City < Base
attr_accessor :id, :label, :bbox, :geometry, :paginator, :collection

attr_writer :name, :type, :zone_type, :postcode, :city
alias places collection

def initialize(attributes: {},
geometry: NULL_ISLAND,
ignore_undefined_attributes: false,
collection: [], paginator: nil)
@collection = collection
@paginator = paginator

super(
attributes: attributes,
geometry: geometry,
ignore_undefined_attributes: ignore_undefined_attributes
)
end

def slug
name.to_slug.normalize.to_s
end

def name
@name || 'onbekend'
end
end
end
end

+ 15
- 6
app/models/place.rb View File

@@ -23,8 +23,8 @@ module Hours
PARSER = OpeningHoursConverter::OpeningHoursParser.new

attr_accessor :id, :place_id, :name,
:region_slug, :distance, :website
attr_writer :address, :opening_hours, :geometry
:distance, :website, :administrative_regions
attr_writer :opening_hours, :geometry

def status
return :unknown if opening_hours&.empty?
@@ -34,6 +34,10 @@ module Hours
:unknown
end

def region_slug
(address&.city || 'onbekend').to_slug.normalize.to_s
end

def open_this_week
date_ranges = PARSER.parse(opening_hours)
get_intervals_as_week(date_ranges, Date.today)
@@ -45,10 +49,6 @@ module Hours
OpenStruct.new(raw_address)
end

def region
address&.city
end

def raw_address
@address
end
@@ -61,6 +61,15 @@ module Hours
@geometry || null_island
end

def city=(city)
@address ||= {}
@address[:city] = city
end

def address=(address = {})
@address = (address || {}).merge(@address || {})
end

private

def get_intervals_as_week(date_ranges, date_in_week)

+ 0
- 30
app/models/place_index.rb View File

@@ -1,30 +0,0 @@
# frozen_string_literal: true

require 'georuby'

require_relative 'base_collection.rb'
require_relative 'place.rb'

module Hours
module Models
##
# A collection of places
class PlaceIndex < BaseCollection
ITEM_CLASS = ::Hours::Models::Place
NULLITEM_CLASS = ::Hours::Models::NullPlace

attr_accessor :centerpoint

def initialize(dataset, paginator = nil, centerpoint = nil)
super(dataset, paginator)
@centerpoint = centerpoint || null_island
end

private

def null_island
GeoRuby::SimpleFeatures::Point.from_xy(0, 0)
end
end
end
end

+ 0
- 23
app/models/region.rb View File

@@ -1,23 +0,0 @@
# frozen_string_literal: true

require_relative 'base.rb'
require_relative 'place_index.rb'

module Hours
module Models
##
# Region is a collection of Places belonging to one region.
# It is, therefore, a decorator for a list of places.
class Region < PlaceIndex
def initialize(dataset,
paginator = nil, centerpoint = nil, region_slug = '')
@region_slug = region_slug || ''
super(dataset, paginator, centerpoint)
end

def name
@region_slug.capitalize
end
end
end
end

+ 17
- 6
app/models/search_result.rb View File

@@ -1,21 +1,32 @@
# frozen_string_literal: true

require_relative 'base.rb'
require_relative 'place_index.rb'

module Hours
module Models
##
# Region is a collection of Places belonging to one region.
# It is, therefore, a decorator for a list of places.
class SearchResult < PlaceIndex
attr_reader :query, :error
class SearchResult
attr_reader :query, :error, :paginator
ITEM_CLASS = ::Hours::Models::Place
NULLITEM_CLASS = ::Hours::Models::NullPlace

## TODO: PlaceIndex and other models need initialize with keyword args
def initialize(dataset: [], paginator: nil, query: '', error: nil)
def initialize(collection: [], paginator: nil, query: '', error: nil)
@query = query
@error = error
super(dataset, paginator)
@collection = collection
@paginator = paginator
end

def collection
@collection.map do |item|
if item.nil?
NULLITEM_CLASS.new
else
ITEM_CLASS.from_geojson_feature(item)
end
end
end
end
end

+ 77
- 0
app/projections/city_query.rb View File

@@ -0,0 +1,77 @@
# frozen_string_literal: true

require 'pagy/backend'
require 'pagy/extras/array'

module Hours
module Projections
# Query handler that builds a list of places in a City
class CityQuery
attr_reader :page
include Pagy::Backend

def self.build
faraday = Faraday.new(url: ENV['BRAGI_URL']) do |conn|
conn.response :raise_error
conn.adapter Faraday.default_adapter
end
new(faraday)
end

def initialize(http_client)
@http_client = http_client
end

def handle(slug, page = 1)
@slug = slug
@page = page

@city = city
@city.paginator, @city.collection = pagy_array(places)

@city
end

def pagy_array_get_vars(collection, vars)
vars[:count] = collection.count
vars[:page] = page
vars
end

private

def city
response = @http_client.get('/autocomplete', city_params)

Hours::Models::City.from_geojson_feature(
RGeo::GeoJSON.decode(response.body).first
)
end

def places
## TODO: consider making the query of collection lazy.
response = @http_client.get('/features', city_center_params)
places = RGeo::GeoJSON.decode(response.body)

places.map do |feature|
Hours::Models::Place.from_geojson_feature(feature)
end.to_a
end

def city_params
{ q: @slug,
limit: 1,
type: ['city'] }
end

def city_center_params
{
lat: @city.geometry.y,
lon: @city.geometry.x,
limit: 20,
type: ['poi']
}
end
end
end
end

+ 1
- 2
app/projections/place_query.rb View File

@@ -2,7 +2,6 @@

module Hours
module Projections

# Query handler that queries the projection table for a single node
class PlaceQuery
def self.build
@@ -23,7 +22,7 @@ module Hours
RGeo::GeoJSON.decode(response.body).first
)
rescue Faraday::ServerError, JSON::ParserError => e
Hours::Models::NullPlace.new(error: e.message)
Hours::Models::NullPlace.new(attributes: { error: e.message })
end
end
end

+ 0
- 45
app/projections/region_query.rb View File

@@ -1,45 +0,0 @@
# frozen_string_literal: true

require 'offline_geocoder'

module Hours
module Projections
# Query handler that builds a list of places in a Region
class RegionQuery < BaseQuery
def handle(slug, page = 1)
@page = page
@region_slug = slug
return Hours::Models::Region.new([], {}, nil, nil) unless region

pagy, records = pagy(dataset.order(distance).where(in_envelope))
Hours::Models::Region.new(records,
pagy,
region[:centerpoint],
region[:name])
end

private

def region
raise ArgumentError if @region_slug.nil? || @region_slug.empty?

@region ||= Hours.projections_database[:query_regions]
.first(slug: @region_slug)
end

def distance
Sequel.lit('location <-> ?', region[:centerpoint])
end

def in_envelope
Sequel.lit('location && ST_MakeEnvelope(?, ?, ?, ?, 4326)',
*envelope_corners)
end

def envelope_corners
cp = region[:centerpoint]
[cp.x + BUFFERX, cp.y + BUFFERY, cp.x - BUFFERX, cp.y - BUFFERY]
end
end
end
end

+ 1
- 1
app/projections/search_query.rb View File

@@ -30,7 +30,7 @@ module Hours
features = get_bragi_features(query)
pagy, places = pagy_array(features)
Hours::Models::SearchResult.new(
dataset: places,
collection: places,
paginator: pagy,
query: query
)

+ 1
- 1
app/views/layout.erb View File

@@ -27,7 +27,7 @@
<%== yield %>
</div>
<script>
<%== content_for(:closing_js) %>
<%== content_for(:closing_js) %>
</script>
</body>
</html>

+ 13
- 8
app/views/region.erb View File

@@ -1,10 +1,10 @@
<% if @region.empty? %>
<% if @region.places.empty? %>
<p class="alert alert-primary" role="alert">
No places found in <%= @region.name %>
</p>
<% else %>
<%-
js = "var map = L.map('map').setView([#{@region.centerpoint.y}, #{@region.centerpoint.x}], 16);
js = "var map = L.map('map').setView([#{@region.geometry.y}, #{@region.geometry.x}], 16);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors'
}).addTo(map);"
@@ -42,10 +42,10 @@
popupAnchor: [-20, -40],
});"

js += "L.marker([#{@region.centerpoint.y}, #{@region.centerpoint.x}], {icon: centerIcon}).addTo(map);"
js += "L.marker([#{@region.geometry.y}, #{@region.geometry.x}], {icon: centerIcon}).addTo(map);"
js += "var markers = [];"

@region.each do |place|
@region.collection.each do |place|
icon = if place.status == :open
'openedIcon'
elsif place.status == :closed
@@ -55,17 +55,22 @@
end
popup_content = "<strong>#{Rack::Utils.escape_html(place.name)}</strong>"
popup_content += erb(:status_badge_partial, locals: { status: place.status }).delete("\n")
js += "markers.push(L.marker([#{place.location.y}, #{place.location.x}], {icon: #{icon}}).addTo(map).bindPopup('#{popup_content}'));"
js += "markers.push(L.marker([#{place.geometry.y}, #{place.geometry.x}], {icon: #{icon}}).addTo(map).bindPopup('#{popup_content}'));"
end
js += "var group = L.featureGroup(markers);"
js += "map.fitBounds(group.getBounds());"

#js += "map.fitBounds([[#{@region.bbox[1]}, #{@region.bbox[0]}], [#{@region.bbox[3]}, #{@region.bbox[2]}]]);"

set_content_for(:closing_js, js)
%>

<% set_content_for(:region_slug, @region.slug) %>
<% set_content_for(:region_name, @region.name) %>

<h2>Openingstijden in <%= @region.name %></h2>

<section class="row">
<div class="col-3 list-group">
<%- @region.each do |place| %>
<%- @region.collection.each do |place| %>
<a href="/places/<%= place.id %>" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h3 class="mb-1 small"><%= place.name %></h3>

+ 1
- 1
app/views/search.erb View File

@@ -2,7 +2,7 @@

<section class="row">
<div class="col-3 list-group">
<%- @search_result.each do |place| %>
<%- @search_result.collection.each do |place| %>
<a href="/places/<%= place.id %>" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h3 class="mb-1 small"><%= place.name %></h3>

+ 1
- 1
lib/app.rb View File

@@ -124,7 +124,7 @@ module Hours
end

get '/in/:slug', provides: 'html' do
@region = Hours::Projections::RegionQuery.build.handle(
@region = Hours::Projections::CityQuery.build.handle(
params[:slug],
page_param
)

+ 1
- 0
test/fixtures/input/region_nijmegen.json View File

@@ -0,0 +1 @@
{"type":"FeatureCollection","geocoding":{"version":"0.1.0","query":""},"features":[{"type":"Feature","geometry":{"coordinates":[5.8634696,51.8427385],"type":"Point"},"properties":{"geocoding":{"id":"admin:osm:relation:1201020","type":"zone","zone_type":"city","label":"Nijmegen","name":"Nijmegen","postcode":null,"city":null,"citycode":"","level":8,"administrative_regions":[],"codes":[{"name":"ref:gemeentecode","value":"268"},{"name":"wikidata","value":"Q47887"}],"bbox":[5.7576206,51.7905891,5.9083469,51.8946209]}}}]}

+ 37
- 0
test/fixtures/vcr_cassettes/bragi_jan_de_groot.yml View File

@@ -0,0 +1,37 @@
---
http_interactions:
- request:
method: get
uri: http://localhost:4000/features/poi:osm:node:945471470
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- Faraday v1.0.0
response:
status:
code: 200
message: OK
headers:
content-length:
- '2278'
connection:
- close
cache-control:
- max-age=3600
content-type:
- application/json
date:
- Wed, 22 Apr 2020 09:13:51 GMT
body:
encoding: UTF-8
string: '{"type":"FeatureCollection","geocoding":{"version":"0.1.0","query":""},"features":[{"type":"Feature","geometry":{"coordinates":[5.2966174,51.690227],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:945471470","type":"poi","label":"Jan
de Groot (''s-Hertogenbosch)","name":"Jan de Groot","postcode":"5211TW","city":"''s-Hertogenbosch","citycode":"","administrative_regions":[{"id":"admin:osm:relation:162798","insee":"","level":10,"label":"''s-Hertogenbosch,
Noord-Brabant, Nederland","name":"''s-Hertogenbosch","zip_codes":[],"coord":{"lon":5.295758880751707,"lat":51.71000807857934},"bbox":[5.2064942,51.6639966,5.3822104,51.7557341],"zone_type":"city","parent_id":"admin:osm:relation:47696","codes":[{"name":"ref:woonplaatscode","value":"1595"},{"name":"wikidata","value":"Q2766547"}]},{"id":"admin:osm:relation:47696","insee":"","level":4,"label":"Noord-Brabant,
Nederland","name":"Noord-Brabant","zip_codes":[],"coord":{"lon":5.3031044,"lat":51.688935099999995},"bbox":[4.1901242,51.2209094,6.0481207999999995,51.830751],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-NB"},{"name":"ref:provinciecode","value":"30"},{"name":"wikidata","value":"Q1101"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744389],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:shop:bakery","name":"Bakkerij"}],"properties":[{"key":"addr:city","value":"''s-Hertogenbosch"},{"key":"addr:housenumber","value":"24"},{"key":"addr:postcode","value":"5211TW"},{"key":"addr:street","value":"Stationsweg"},{"key":"name","value":"Jan
de Groot"},{"key":"shop","value":"bakery"},{"key":"source","value":"BAG"},{"key":"source:date","value":"2014-02-11"},{"key":"toilets:wheelchair","value":"no"},{"key":"website","value":"https://www.bosschebollen.nl/"},{"key":"wheelchair","value":"limited"}],"address":{"id":"addr:5.2966249;51.6902236:24","type":"house","label":"Stationsweg
24","name":"Stationsweg 24","housenumber":"24","street":"Stationsweg","postcode":"5211TW","city":null,"citycode":null,"administrative_regions":[]}}}}]}'
http_version: null
recorded_at: Wed, 22 Apr 2020 09:13:51 GMT
recorded_with: VCR 5.1.0

+ 63
- 0
test/fixtures/vcr_cassettes/city_arnhem.yml
File diff suppressed because it is too large
View File


+ 62
- 0
test/fixtures/vcr_cassettes/city_den_bosch.yml
File diff suppressed because it is too large
View File


+ 64
- 0
test/fixtures/vcr_cassettes/city_eindhoven.yml
File diff suppressed because it is too large
View File


+ 63
- 0
test/fixtures/vcr_cassettes/city_nijmegen.yml
File diff suppressed because it is too large
View File


+ 64
- 0
test/fixtures/vcr_cassettes/city_zuidwolde.yml
File diff suppressed because it is too large
View File


+ 198
- 0
test/fixtures/vcr_cassettes/city_zuidwolde_drenthe.yml View File

@@ -0,0 +1,198 @@
---
http_interactions:
- request:
method: get
uri: http://localhost:4000/autocomplete?limit=1&q=zuidwolde-drenthe&type%5B%5D=city
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- Faraday v1.0.0
response:
status:
code: 200
message: OK
headers:
content-length:
- '1276'
connection:
- close
cache-control:
- max-age=3600
content-type:
- application/json
date:
- Sun, 14 Jun 2020 16:09:08 GMT
body:
encoding: UTF-8
string: '{"type":"FeatureCollection","geocoding":{"version":"0.1.0","query":""},"features":[{"type":"Feature","geometry":{"coordinates":[6.41926898445426,52.66255725914056],"type":"Point"},"properties":{"geocoding":{"id":"admin:osm:relation:2681061","type":"zone","zone_type":"city","label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","postcode":null,"city":null,"citycode":"","level":10,"administrative_regions":[{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}],"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816]}}}]}'
http_version: null
recorded_at: Sun, 14 Jun 2020 16:09:08 GMT
- request:
method: get
uri: http://localhost:4000/features?lat=52.66255725914056&limit=20&lon=6.41926898445426&type%5B%5D=poi
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- Faraday v1.0.0
response:
status:
code: 200
message: OK
headers:
content-length:
- '61250'
connection:
- close
cache-control:
- max-age=3600
content-type:
- application/json
date:
- Sun, 14 Jun 2020 16:09:08 GMT
body:
encoding: UTF-8
string: '{"type":"FeatureCollection","geocoding":{"version":"0.1.0","query":""},"features":[{"type":"Feature","geometry":{"coordinates":[6.4186128,52.666644899999994],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:1591501026","type":"poi","label":"Cultuurhistorisch
Museum de Wemme (Zuidwolde)","name":"Cultuurhistorisch Museum de Wemme","postcode":"7921KB","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:museum","name":"Museum"}],"properties":[{"key":"addr:city","value":"Zuidwolde"},{"key":"addr:housenumber","value":"49"},{"key":"addr:postcode","value":"7921KB"},{"key":"addr:street","value":"Burgemeester
Tonckensstraat"},{"key":"name","value":"Cultuurhistorisch Museum de Wemme"},{"key":"tourism","value":"museum"},{"key":"website","value":"https://www.dewemme.nl/"}],"address":{"id":"addr:6.4187186;52.6664665:49-ts","type":"house","label":"Burgemeester
Tonckensstraat 49-ts (Zuidwolde)","name":"Burgemeester Tonckensstraat 49-ts","housenumber":"49-ts","street":"Burgemeester
Tonckensstraat","postcode":"7921KB","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":456},{"type":"Feature","geometry":{"coordinates":[6.4198562,52.6669778],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:4154107900","type":"poi","label":"Toeristeninformatie
(Zuidwolde)","name":"Toeristeninformatie","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:information","name":"Toeristeninformatie"}],"properties":[{"key":"bicycle","value":"yes"},{"key":"guidepost","value":"paddenstoel"},{"key":"hiking","value":"yes"},{"key":"horse","value":"yes"},{"key":"information","value":"guidepost"},{"key":"mtb","value":"yes"},{"key":"operator","value":"Nationale
Bewegwijzeringsdienst"},{"key":"ref","value":"23590/001"},{"key":"tourism","value":"information"}],"address":{"id":"addr:6.419561;52.6671246:48","type":"house","label":"Burgemeester
Tonckensstraat 48 (Zuidwolde)","name":"Burgemeester Tonckensstraat 48","housenumber":"48","street":"Burgemeester
Tonckensstraat","postcode":"7921KD","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":493},{"type":"Feature","geometry":{"coordinates":[6.4226535,52.6672818],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:2818938765","type":"poi","label":"BBcare
(Zuidwolde)","name":"BBcare","postcode":"7921EL","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:shop:clothes","name":"Kledingwinkel"}],"properties":[{"key":"addr:city","value":"Zuidwolde"},{"key":"addr:housenumber","value":"2"},{"key":"addr:postcode","value":"7921EL"},{"key":"addr:street","value":"De
Zoom"},{"key":"clothes","value":"women;Mammacare_Adviseur"},{"key":"name","value":"BBcare"},{"key":"operator","value":"Betty
van den Berg"},{"key":"shop","value":"clothes"},{"key":"source","value":"BAG"},{"key":"source:date","value":"2014-03-24"}],"address":{"id":"addr:6.4226909;52.6672846:2","type":"house","label":"De
Zoom 2 (Zuidwolde)","name":"De Zoom 2","housenumber":"2","street":"De Zoom","postcode":"7921EL","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":572},{"type":"Feature","geometry":{"coordinates":[6.419629,52.669721499999994],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:4154107936","type":"poi","label":"Toeristeninformatie
(Zuidwolde)","name":"Toeristeninformatie","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:information","name":"Toeristeninformatie"}],"properties":[{"key":"bicycle","value":"yes"},{"key":"guidepost","value":"paddenstoel"},{"key":"hiking","value":"yes"},{"key":"horse","value":"yes"},{"key":"information","value":"guidepost"},{"key":"mtb","value":"yes"},{"key":"operator","value":"Nationale
Bewegwijzeringsdienst"},{"key":"ref","value":"23589/001"},{"key":"tourism","value":"information"}],"address":{"id":"addr:6.419885;52.6699641:16c","type":"house","label":"Westerveldseweg
16c (Zuidwolde)","name":"Westerveldseweg 16c","housenumber":"16c","street":"Westerveldseweg","postcode":"7921NB","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":796},{"type":"Feature","geometry":{"coordinates":[6.428754199999999,52.6694232],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:2590212313","type":"poi","label":"Chinees
Indisch Restaurant Tong-Fang (Zuidwolde)","name":"Chinees Indisch Restaurant
Tong-Fang","postcode":"7921AR","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:restaurant","name":"Restaurant"}],"properties":[{"key":"addr:city","value":"Zuidwolde"},{"key":"addr:housenumber","value":"122"},{"key":"addr:postcode","value":"7921AR"},{"key":"addr:street","value":"Hoofdstraat"},{"key":"amenity","value":"restaurant"},{"key":"contact:email","value":"tongfang@live.nl"},{"key":"contact:phone","value":"+31
528 372665"},{"key":"contact:website","value":"http://www.chineeszuidwolde.nl/"},{"key":"cuisine","value":"chinese"},{"key":"name","value":"Chinees
Indisch Restaurant Tong-Fang"}],"address":{"id":"addr:6.4286319;52.6694253:122","type":"house","label":"Hoofdstraat
122 (Zuidwolde)","name":"Hoofdstraat 122","housenumber":"122","street":"Hoofdstraat","postcode":"7921AR","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":995},{"type":"Feature","geometry":{"coordinates":[6.414575,52.653766],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:4154107896","type":"poi","label":"Toeristeninformatie
(Zuidwolde)","name":"Toeristeninformatie","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:information","name":"Toeristeninformatie"}],"properties":[{"key":"bicycle","value":"yes"},{"key":"guidepost","value":"paddenstoel"},{"key":"hiking","value":"yes"},{"key":"horse","value":"yes"},{"key":"information","value":"guidepost"},{"key":"mtb","value":"yes"},{"key":"operator","value":"Nationale
Bewegwijzeringsdienst"},{"key":"ref","value":"23591/001"},{"key":"tourism","value":"information"}],"address":{"id":"addr:6.4142362;52.6544594:8","type":"house","label":"Kerkweg
8 (Zuidwolde)","name":"Kerkweg 8","housenumber":"8","street":"Kerkweg","postcode":"7921RP","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1027},{"type":"Feature","geometry":{"coordinates":[6.4295592,52.6703182],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:552561686","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"}],"address":{"id":"addr:6.4298359;52.6704215:1","type":"house","label":"Burgerzinstraat
1 (Zuidwolde)","name":"Burgerzinstraat 1","housenumber":"1","street":"Burgerzinstraat","postcode":"7921JL","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1107},{"type":"Feature","geometry":{"coordinates":[6.4313167,52.669782899999994],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:730786706","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"}],"address":{"id":"street:osm:way:6437187","type":"street","label":"Zuider
Esweg (Zuidwolde)","name":"Zuider Esweg","street":"Zuider Esweg","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1142},{"type":"Feature","geometry":{"coordinates":[6.4294369,52.671040299999994],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:2767669986","type":"poi","label":"Kruidvat
(Zuidwolde)","name":"Kruidvat","postcode":"7921AG","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:shop:chemist","name":"Drogist"}],"properties":[{"key":"addr:city","value":"Zuidwolde"},{"key":"addr:housenumber","value":"111A"},{"key":"addr:postcode","value":"7921AG"},{"key":"addr:street","value":"Hoofdstraat"},{"key":"brand","value":"Kruidvat"},{"key":"brand:wikidata","value":"Q2226366"},{"key":"brand:wikipedia","value":"en:Kruidvat"},{"key":"name","value":"Kruidvat"},{"key":"operator","value":"Kruidvat"},{"key":"shop","value":"chemist"},{"key":"source","value":"BAG"},{"key":"website","value":"https://www.kruidvat.nl/"}],"address":{"id":"addr:6.4294534;52.6710712:111a","type":"house","label":"Hoofdstraat
111a (Zuidwolde)","name":"Hoofdstraat 111a","housenumber":"111a","street":"Hoofdstraat","postcode":"7921AG","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1166},{"type":"Feature","geometry":{"coordinates":[6.4348648,52.667192799999995],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:397000952","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"access","value":"customers"},{"key":"amenity","value":"parking"},{"key":"fee","value":"no"},{"key":"parking","value":"surface"}],"address":{"id":"addr:6.4350924;52.667226:14a","type":"house","label":"Nijverheidsweg
14a (Zuidwolde)","name":"Nijverheidsweg 14a","housenumber":"14a","street":"Nijverheidsweg","postcode":"7921JJ","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1171},{"type":"Feature","geometry":{"coordinates":[6.42943,52.6711342],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:2590383362","type":"poi","label":"Bloemen
(Zuidwolde)","name":"Bloemen","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:shop:florist","name":"Bloemenwinkel"}],"properties":[{"key":"name","value":"Bloemen"},{"key":"shop","value":"florist"}],"address":{"id":"addr:6.4294648;52.6711578:111","type":"house","label":"Hoofdstraat
111 (Zuidwolde)","name":"Hoofdstraat 111","housenumber":"111","street":"Hoofdstraat","postcode":"7921AG","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1174},{"type":"Feature","geometry":{"coordinates":[6.4356186,52.666725],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:397000955","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"},{"key":"parking","value":"surface"}],"address":{"id":"addr:6.4350698;52.6667817:14","type":"house","label":"Nijverheidsweg
14 (Zuidwolde)","name":"Nijverheidsweg 14","housenumber":"14","street":"Nijverheidsweg","postcode":"7921JJ","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1196},{"type":"Feature","geometry":{"coordinates":[6.4305802,52.671006],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:264336812","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"}],"address":{"id":"addr:6.4308575;52.6711259:6a","type":"house","label":"Zuider
Esweg 6a (Zuidwolde)","name":"Zuider Esweg 6a","housenumber":"6a","street":"Zuider
Esweg","postcode":"7921JE","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1210},{"type":"Feature","geometry":{"coordinates":[6.429585599999999,52.6714759],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:2599631016","type":"poi","label":"Grillroom
Yusuf (Zuidwolde)","name":"Grillroom Yusuf","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:restaurant","name":"Restaurant"}],"properties":[{"key":"amenity","value":"restaurant"},{"key":"cuisine","value":"kebab"},{"key":"name","value":"Grillroom
Yusuf"}],"address":{"id":"addr:6.4295908;52.6714781:107a","type":"house","label":"Hoofdstraat
107a (Zuidwolde)","name":"Hoofdstraat 107a","housenumber":"107a","street":"Hoofdstraat","postcode":"7921AG","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1211},{"type":"Feature","geometry":{"coordinates":[6.4359901,52.6667835],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:397000956","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"},{"key":"parking","value":"surface"}],"address":{"id":"addr:6.4360861;52.6664275:1","type":"house","label":"Industrieweg
1 (Zuidwolde)","name":"Industrieweg 1","housenumber":"1","street":"Industrieweg","postcode":"7921JP","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1221},{"type":"Feature","geometry":{"coordinates":[6.4333047,52.6695347],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:730275960","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"}],"address":{"id":"addr:6.43328;52.6695911:17c","type":"house","label":"Zuider
Esweg 17c (Zuidwolde)","name":"Zuider Esweg 17c","housenumber":"17c","street":"Zuider
Esweg","postcode":"7921JC","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1223},{"type":"Feature","geometry":{"coordinates":[6.4358358,52.6674519],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:node:3226450563","type":"poi","label":"Argos
(Zuidwolde)","name":"Argos","postcode":"7921JH","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:fuel","name":"Benzinestation"}],"properties":[{"key":"addr:city","value":"Zuidwolde"},{"key":"addr:housenumber","value":"19"},{"key":"addr:postcode","value":"7921JH"},{"key":"addr:street","value":"Nijverheidsweg"},{"key":"amenity","value":"fuel"},{"key":"brand","value":"Argos"},{"key":"fuel:diesel","value":"yes"},{"key":"fuel:octane_95","value":"yes"},{"key":"name","value":"Argos"},{"key":"opening_hours","value":"24/7"},{"key":"operator","value":"Varo
Energy"},{"key":"self_service","value":"yes"},{"key":"website","value":"https://www.argos.nl/tankstation/argos-zuidwolde/"}],"address":{"id":"addr:6.4362025;52.6676799:19","type":"house","label":"Nijverheidsweg
19 (Zuidwolde)","name":"Nijverheidsweg 19","housenumber":"19","street":"Nijverheidsweg","postcode":"7921JH","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1242},{"type":"Feature","geometry":{"coordinates":[6.4308872,52.6719695],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:263088747","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"}],"address":{"id":"addr:6.4310375;52.6720672:7","type":"house","label":"Zantingehof
7 (Zuidwolde)","name":"Zantingehof 7","housenumber":"7","street":"Zantingehof","postcode":"7921GG","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1307},{"type":"Feature","geometry":{"coordinates":[6.4323877,52.671317599999995],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:730786709","type":"poi","label":"Parkeren
(Zuidwolde)","name":"Parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"}],"address":{"id":"addr:6.4323517;52.6715594:14","type":"house","label":"Oosterweg
14 (Zuidwolde)","name":"Oosterweg 14","housenumber":"14","street":"Oosterweg","postcode":"7921GB","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1315},{"type":"Feature","geometry":{"coordinates":[6.429916899999999,52.67252],"type":"Point"},"properties":{"geocoding":{"id":"poi:osm:way:253032464","type":"poi","label":"parkeren
(Zuidwolde)","name":"parkeren","postcode":null,"city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}],"poi_types":[{"id":"poi_type:amenity:parking","name":"Parkeren"}],"properties":[{"key":"amenity","value":"parking"},{"key":"name","value":"parkeren"},{"key":"parking","value":"surface"}],"address":{"id":"addr:6.4299699;52.6723526:103","type":"house","label":"Hoofdstraat
103 (Zuidwolde)","name":"Hoofdstraat 103","housenumber":"103","street":"Hoofdstraat","postcode":"7921AG","city":"Zuidwolde","citycode":"","administrative_regions":[{"id":"admin:osm:relation:2681061","insee":"","level":10,"label":"Zuidwolde,
Drenthe, Nederland","name":"Zuidwolde","zip_codes":[],"coord":{"lon":6.41926898445426,"lat":52.66255725914056},"bbox":[6.3663966,52.612184899999995,6.466306299999999,52.7069816],"zone_type":"city","parent_id":"admin:osm:relation:47540","codes":[{"name":"ref:woonplaatscode","value":"3172"},{"name":"wikidata","value":"Q2754055"}]},{"id":"admin:osm:relation:47540","insee":"","level":4,"label":"Drenthe,
Nederland","name":"Drenthe","zip_codes":[],"coord":{"lon":6.560553,"lat":52.9953538},"bbox":[6.11982,52.612184899999995,7.0927397,53.203832299999995],"zone_type":"state","parent_id":"admin:osm:relation:47796","codes":[{"name":"ISO3166-2","value":"NL-DR"},{"name":"ref:provinciecode","value":"22"},{"name":"wikidata","value":"Q772"}]},{"id":"admin:osm:relation:47796","insee":"","level":3,"label":"Nederland","name":"Nederland","zip_codes":[],"coord":{"lon":4.8936041,"lat":52.3727598},"bbox":[3.080161,50.7503658,7.227498499999999,53.744025],"zone_type":"country","parent_id":null,"codes":[{"name":"wikidata","value":"Q55"}]}]}}},"distance":1320}]}'
http_version: null
recorded_at: Sun, 14 Jun 2020 16:09:08 GMT
recorded_with: VCR 5.1.0

+ 64
- 0
test/fixtures/vcr_cassettes/city_zuidwolde_groningen.yml
File diff suppressed because it is too large
View File


+ 55
- 77
test/integration/web/view_regions_test.rb View File

@@ -2,45 +2,31 @@

require 'test_helper'

require_relative Hours.base_path.join('test/support/workflows/add_place.rb')
require_relative Hours.base_path.join('test/support/workflows/add_region.rb')

describe 'web views regions' do
include WebTestHelpers
include Workflows::AddPlace

before do
skip
Workflows::AddRegion.new(self).call
end

describe 'GET /in/nijmegen' do
let(:regions) { [json_fixtures('input/nijmegen_city.json')] }
let(:input) do
[
json_fixtures('input/hm_burchtstraat.json'),
json_fixtures('input/marienburg_bicycle.json')
]
end

let(:place_id) { 'poi:osm:node:989225414' }
before do
visit "/places/#{hm_id}"
click_link 'in Nijmegen'
VCR.use_cassette :bragi_hm_nijmegen do
visit "/places/#{place_id}"
end

VCR.use_cassette :city_nijmegen do
click_link 'in Nijmegen'
end
end

it 'follows link to index' do
assert_current_path page, 'http://www.example.com/in/nijmegen'

assert_selector page, 'h2', text: 'Openingstijden in Nijmegen'
assert_selector page, 'h3', text: 'H&M'
assert_selector page, 'h3', text: 'Kattencafé Balthazar'
end

describe 'with 21 items in nijmegen' do
# Reverse to avoid false positives because of insert order
let(:nijmegen) { geojson_fixtures('input/nijmegen_city.json') }
let(:input) { list_of_geojson(21, nijmegen.geometry).reverse }

it 'pages the index' do
skip 'Re-implement paging'
assert_current_path page, 'http://www.example.com/in/nijmegen'
assert_equal 20, page.find_all('a.list-group-item').length

@@ -54,8 +40,8 @@ describe 'web views regions' do

it 'sorts them from the center of "Nijmegen" do' do
items = page.find_all('a.list-group-item')
assert_text items[0], 'place #0'
assert_text items[1], 'place #1'
assert_text items[0], 'Gotcha'
assert_text items[1], 'Sid & Liv'
end
end
end
@@ -63,33 +49,19 @@ describe 'web views regions' do
# This tests that we actually use the centroid.
# Also tests against "real world" distances.
describe 'GET /in/arnhem' do
let(:regions) { [json_fixtures('input/arnhem_city.json')] }
let(:input) do
[
json_fixtures('input/hm_arnhem.json'),
json_fixtures('input/ekoplaza_arnhem.json')
]
before do
VCR.use_cassette :city_arnhem do
visit '/in/arnhem'
end
end

it 'sorts them from the centroid of Arnhem' do
visit '/in/arnhem'

assert_no_text page, 'No places found in Arnhem'

items = page.find_all('a.list-group-item')
# Ecoplaza is nearest to centroid
assert_text items[0], 'Ekoplaza'
assert_text items[1], 'H&M'
end
end

describe 'GET /in/zuidwolde supports tiny hamlets' do
let(:regions) { [json_fixtures('input/zuidwolde_gn_region.json')] }
let(:input) { [json_fixtures('input/zuidwolde_fastfood.json')] }

it 'supports tiny hamlets' do
visit '/in/zuidwolde'
assert_text page, 'Moeke Vaatstra'
assert_text items[0], "Domino's Pizza"
assert_text items[1], 'Park'
end
end

@@ -97,62 +69,68 @@ describe 'web views regions' do
# As a user living in a city that shares a name with other cities
# When I look up my region
# Then I get places only related to my region.
# Zuidwolde GN: Moeke Vaatstra
# Zuidwolde Drente: Grillroom Yusuf
describe 'GET /in/zuidwolde with duplicate names' do
let(:regions) do
[
json_fixtures('input/zuidwolde_gn_region.json'),
json_fixtures('input/zuidwolde_dr_region.json')
]
end
# All places are in villages called "Zuidwolde".
# Both villages "Zuidwolde" are in separate provinces
# One village (in Groningen) has two places,
# the other (in Drenthe) only one. Groningen one is "more popular".
let(:input) do
[
json_fixtures('input/zuidwolde_bb.json'),
json_fixtures('input/zuidwolde_fastfood.json'),
json_fixtures('input/zuidwolde_grillroom.json')
]
# TODO: this should probably redirect to Zuidwolde-groningen
# instead.
it 'has a region zuidwolde' do
VCR.use_cassette :city_zuidwolde do
visit '/in/zuidwolde'
end

assert_text page, 'Moeke Vaatstra'

assert_no_text page, 'Grillroom Yusuf'
end

it 'has a region zuidwolde' do
visit '/in/zuidwolde'
it 'has a region zuidwolde-groningen' do
VCR.use_cassette :city_zuidwolde_groningen do
visit '/in/zuidwolde-groningen'
end

assert_text page, 'Moeke Vaatstra'
assert_text page, "Bed en brood 'Irene'"

assert_no_text page, 'Grillroom Yusuf'
end

it 'has a region zuidwolde-1' do
visit '/in/zuidwolde-1'
it 'has a region zuidwolde-drenthe' do
# Searches for Zuidwolde, Drenthe in bragi
VCR.use_cassette :city_zuidwolde_drenthe do
visit '/in/zuidwolde-drenthe'
end

assert_text page, 'Grillroom Yusuf'

assert_no_text page, 'Moeke Vaatstra'
assert_no_text page, "Bed en brood 'Irene'"
end
end

describe 'region with complex characters' do
let(:regions) { [json_fixtures('input/denbosch_city.json')] }
let(:input) { [json_fixtures('input/jan_de_groot_shertogenbosch.json')] }
let(:place_id) { 'poi:osm:node:945471470' }

it 'Renders region name with UTF8 but slug is normalized' do
visit "/places/#{aggregate_id}"
click_link "'s-Hertogenbosch"
VCR.use_cassette :bragi_jan_de_groot do
visit "/places/#{place_id}"
end

assert_link page, "'s-Hertogenbosch"

VCR.use_cassette :city_den_bosch do
click_link "'s-Hertogenbosch"
end

assert_current_path page, 'http://www.example.com/in/s-hertogenbosch'
end
end

describe 'GET /in/eindhoven empty place' do
let(:regions) { [json_fixtures('input/eindhoven_city.json')] }
let(:input) { [json_fixtures('input/hm_arnhem.json')] }

it 'shows empty text' do
visit '/in/eindhoven'

skip 'implement searching with bounding box. Now it returns items'\
' ordered from NULL_ISLAND'
VCR.use_cassette :city_eindhoven do
visit '/in/eindhoven'
end
assert_text page, 'No places found in Eindhoven'
end
end

+ 0
- 48
test/models/base_collection_test.rb View File

@@ -1,48 +0,0 @@
# frozen_string_literal: true

require 'test_helper'
require_relative Hours.base_path.join 'app/models/base_collection.rb'

describe Hours::Models::BaseCollection do
module Hours
module Models
class Mock < Hours::Models::Base
attr_accessor :id
end
class MockCollection < BaseCollection
ITEM_CLASS = Mock
NULLITEM_CLASS = Class
end
end
end

let(:row) { { id: 'PK' } }
let(:dataset) { [row] }

subject do
Hours::Models::MockCollection.new(dataset)
end

it 'is a collection of defined classes' do
assert_kind_of Enumerable, subject

subject.each do |place|
assert_kind_of Hours::Models::Mock, place
end
assert_equal row[:id], subject.first.id
end

it 'delegates all methods to the dataset' do
dataset = OpenStruct.new(weird_method: 'weird answer')
subject = Hours::Models::MockCollection.new(dataset)
# Delegator interfereces with Minitest::Mock so we test with our own
# mock
assert_equal 'weird answer', subject.weird_method
end

it 'has a paginator object' do
paginator = Pagy.new(count: 1)
subject = Hours::Models::MockCollection.new(dataset, paginator)
assert_equal paginator, subject.paginator
end
end

+ 2
- 2
test/models/base_test.rb View File

@@ -10,13 +10,13 @@ describe Hours::Models::Base do

describe '.initialize' do
it 'sets accessible attributes' do
subject = MockModel.new(name: 'Hi')
subject = MockModel.new(attributes: { name: 'Hi' })
assert_equal 'Hi', subject.name
end

it 'raises on undefined methods' do
assert_raises NoMethodError do
MockModel.new(fakemethod: 'val')
MockModel.new(attributes: { fakemethod: 'val' })
end
end
end

+ 47
- 0
test/models/city_test.rb View File

@@ -0,0 +1,47 @@
# frozen_string_literal: true

require 'test_helper'

describe Hours::Models::City do
let(:attributes) do
{ id: 'admin:osm:relation:42', name: "'s Hertogenbosch" }
end
let(:collection) { [:row] }
let(:paginator) { { count: 1 } }

subject do
Hours::Models::City.new(attributes: attributes,
ignore_undefined_attributes: true,
collection: collection,
paginator: paginator)
end

describe 'attributes' do
let(:read_write) { %i[id name label bbox] }

it 'has a list of read-write attributes' do
kv_attrs = Hash[read_write.map { |attr| [attr, "#{attr}-value"] }]
subject = Hours::Models::City.new(attributes: kv_attrs)
read_write.each do |attr|
assert_equal "#{attr}-value", subject.send(attr)
end
end
end

it 'has a collection of pois' do
assert_equal collection, subject.places
end

it 'has a paginator' do
assert_equal paginator, subject.paginator
end

it 'has a slug from the city name' do
assert_equal 's-hertogenbosch', subject.slug
end

it 'handles nil for name' do
subject.name = nil
assert_equal 'onbekend', subject.slug
end
end

+ 0
- 27
test/models/place_index_test.rb View File

@@ -1,27 +0,0 @@
# frozen_string_literal: true

require 'test_helper'

describe Hours::Models::PlaceIndex do
let(:row) { { id: 'PK' } }
let(:dataset) { [row] }
let(:centerpoint) { :centerpoint_mock }

subject do
Hours::Models::PlaceIndex.new(dataset)
end

it 'is a collection of places' do
assert_kind_of Hours::Models::Place, subject.first
end

it 'has a centerpoint' do
subject = Hours::Models::PlaceIndex.new(dataset, nil, centerpoint)
assert_equal centerpoint, subject.centerpoint
end

it 'has a default centerpoint' do
subject = Hours::Models::PlaceIndex.new(dataset, nil, nil)
assert_equal null_island, subject.centerpoint
end
end

+ 12
- 9
test/models/place_test.rb View File

@@ -18,35 +18,38 @@ describe Hours::Models::Place do

describe 'address' do
before do
subject.address = { city: 'Nijmegen' }
subject.city = 'Nijmegen'
# To test that we don't overwrite it later, explicity set to nil
subject.address = { city: nil }
end

it 'has a raw address' do
assert_equal({ city: 'Nijmegen' }, subject.raw_address)
end

it 'has a city' do
assert_equal 'Nijmegen', subject.address.city
it 'sets address city from top-level city' do
subject.city = 'Arnhem'
assert_equal 'Arnhem', subject.address.city
end

it 'handles nil addresses' do
subject.address = nil
assert_nil subject.address&.city
assert_nil subject.address&.postcode
end
end

describe 'region' do
describe 'region_slug' do
describe 'with city' do
before { subject.address = { city: 'Nijmegen' } }
before { subject.city = "'s-Hertogenbosch" }

it 'uses the city' do
assert_equal 'Nijmegen', subject.region
it 'uses the city, normalized' do
assert_equal 's-hertogenbosch', subject.region_slug
end
end

it 'handles nil addresses' do
subject.address = nil
assert_nil subject.region
assert_equal 'onbekend', subject.region_slug
end
end


+ 0
- 27
test/models/region_test.rb View File

@@ -1,27 +0,0 @@
# frozen_string_literal: true

require 'test_helper'

describe Hours::Models::Region do
let(:row) { { id: 'PK' } }
let(:dataset) { [row] }
let(:pager) { nil }
let(:center) { nil }
let(:region_slug) { 'nijmegen' }

subject do
Hours::Models::Region.new(dataset, pager, center, region_slug)
end

it 'is a collection of places' do
assert_kind_of Hours::Models::Place, subject.first
end

describe '#name' do
let(:row) { nil }

it 'uses the region_slug capitalized' do
assert_equal 'Nijmegen', subject.name
end
end
end

+ 8
- 8
test/models/search_result_test.rb View File

@@ -2,21 +2,21 @@

require 'test_helper'

describe Hours::Models::Region do
let(:row) { { id: 'PK' } }
let(:dataset) { [row] }
describe Hours::Models::SearchResult do
let(:row) { OpenStruct.new(properties: {}) }
let(:collection) { [row] }

subject do
Hours::Models::SearchResult.new(dataset: dataset)
Hours::Models::SearchResult.new(collection: collection)
end

it 'is a collection of places' do
assert_kind_of Hours::Models::Place, subject.first
it 'has a collection of places' do
assert_kind_of Hours::Models::Place, subject.collection.first
end

describe '#query' do
subject do
Hours::Models::SearchResult.new(dataset: dataset, query: 'Smullers')
Hours::Models::SearchResult.new(collection: collection, query: 'Smullers')
end

it 'returns the passed-in query' do
@@ -26,7 +26,7 @@ describe Hours::Models::Region do

describe '#error' do
subject do
Hours::Models::SearchResult.new(dataset: dataset, error: 'An Error')
Hours::Models::SearchResult.new(collection: collection, error: 'An Error')
end

it 'returns the passed-in error' do

+ 45
- 0
test/projections/city_query_test.rb View File

@@ -0,0 +1,45 @@
# frozen_string_literal: true

require 'test_helper'
require 'geo_ruby/geojson'

describe Hours::Projections::CityQuery do
let(:body) do
{
type: 'FeatureCollection',
features: [
{ type: 'Feature',
geometry: { type: 'Point', coordinates: [102.0, 0.5] },
properties: {} }
]
}
end

let(:search_response) { OpenStruct.new(body: body.to_json, code: 200) }
let(:features_response) { OpenStruct.new(body: body.to_json, code: 200) }
let(:emtpy_response) { OpenStruct.new(body: '{}', code: 200) }
let(:error_response) { OpenStruct.new(body: '', code: 500) }

let(:http_client) do
Minitest::Mock.new
end

subject do
Hours::Projections::CityQuery.new(http_client)
end

it '#handle fetches a single city and then its places from bragi' do
http_client.expect(
:get,
search_response,
['/autocomplete', { q: 'nijmegen', limit: 1, type: ['city'] }]
)
http_client.expect(
:get,
features_response,
['/features', { type: ['poi'], lat: 0.5, lon: 102.0, limit: 20 }]
)
assert_kind_of Hours::Models::City, subject.handle('nijmegen')
assert_mock http_client
end
end

+ 0
- 81
test/projections/place_query_test.rb View File

@@ -53,84 +53,3 @@ describe Hours::Projections::PlaceQuery do
end
end
end

describe Hours::Projections::RegionQuery do
before do
skip 'Implement region query from bragi'
end
let(:regions) do
[
json_fixtures('input/nijmegen_city.json'),
json_fixtures('input/arnhem_city.json')
]
end

let(:nijmegen) { geojson_fixtures('input/nijmegen_city.json') }
let(:arnhem) { geojson_fixtures('input/arnhem_city.json') }

subject do
Hours::Projections::RegionQuery.build
end

it '#handle fetches a Region' do
assert_kind_of Hours::Models::Region, subject.handle('nijmegen')
end

it 'pages from :query_places in pages of 20' do
20.times.each do
assert subject.dataset.insert(
id: SecureRandom.uuid,
place_id: SecureRandom.hex,
region_slug: 'TODO-REMOVE',
location: nijmegen.geometry
)
end
assert subject.dataset.insert(
id: SecureRandom.uuid,
place_id: SecureRandom.hex,
region_slug: 'TODO-REMOVE',
location: arnhem.geometry
)

assert_equal 22, subject.dataset.count

result = subject.handle('nijmegen', 1)
assert_equal 20, result.count
assert_kind_of Hours::Models::Place, result.first
end

it 'sorts the results by distance from region center' do
# Counting down to avoid false positive because of insert order
location = nijmegen.geometry.dup
Array.new(3) do
location.x += 0.00001
assert subject.dataset.insert(
id: SecureRandom.uuid,
place_id: SecureRandom.hex,
region_slug: 'TODO-REMOVE',
location: location
)
end
result = subject.handle('nijmegen')
assert_equal nijmegen.geometry, result.centerpoint

places = result.to_a
distance0 = nijmegen.geometry.euclidian_distance(places[0].location)
distance1 = nijmegen.geometry.euclidian_distance(places[1].location)
assert distance1 > distance0
end

describe 'avoid looking up places without regions' do
it '#handle does not allow nil for slug' do
assert_raises ArgumentError do
subject.handle(nil)
end
end

it '#handle does not allow empty string for slug' do
assert_raises ArgumentError do
subject.handle('')
end
end
end
end

+ 0
- 85
test/projections/region_query_test.rb View File

@@ -1,85 +0,0 @@
# frozen_string_literal: true

require 'test_helper'
require 'geo_ruby/geojson'

describe Hours::Projections::RegionQuery do
before do
skip 'Implement region query from bragi'
end
let(:regions) do
[
json_fixtures('input/nijmegen_city.json'),
json_fixtures('input/arnhem_city.json')
]
end

let(:nijmegen) { geojson_fixtures('input/nijmegen_city.json') }
let(:arnhem) { geojson_fixtures('input/arnhem_city.json') }

subject do
Hours::Projections::RegionQuery.build
end

it '#handle fetches a Region' do
assert_kind_of Hours::Models::Region, subject.handle('nijmegen')
end

it 'pages from :query_places in pages of 20' do
20.times.each do
assert subject.dataset.insert(
id: SecureRandom.uuid,
place_id: SecureRandom.hex,
region_slug: 'TODO-REMOVE',
location: nijmegen.geometry
)
end
assert subject.dataset.insert(
id: SecureRandom.uuid,
place_id: SecureRandom.hex,
region_slug: 'TODO-REMOVE',
location: arnhem.geometry
)

assert_equal 22, subject.dataset.count

result = subject.handle('nijmegen', 1)
assert_equal 20, result.count
assert_kind_of Hours::Models::Place, result.first
end

it 'sorts the results by distance from region center' do
# Counting down to avoid false positive because of insert order
location = nijmegen.geometry.dup
Array.new(3) do
location.x += 0.00001
assert subject.dataset.insert(
id: SecureRandom.uuid,
place_id: SecureRandom.hex,
region_slug: 'TODO-REMOVE',
location: location
)
end
result = subject.handle('nijmegen')
assert_equal nijmegen.geometry, result.centerpoint

places = result.to_a
distance0 = nijmegen.geometry.euclidian_distance(places[0].location)
distance1 = nijmegen.geometry.euclidian_distance(places[1].location)
assert distance1 > distance0
end

describe 'avoid looking up places without regions' do
it '#handle does not allow nil for slug' do
assert_raises ArgumentError do
subject.handle(nil)
end
end

it '#handle does not allow empty string for slug' do
assert_raises ArgumentError do
subject.handle('')
end
end
end
end

Loading…
Cancel
Save