slippy_tiles_scorer 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -10
- data/lib/slippy_tiles_scorer/cluster.rb +26 -28
- data/lib/slippy_tiles_scorer/max_square.rb +32 -15
- data/lib/slippy_tiles_scorer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95be9f898e6231b3595f43b3b35baf834e5eba161e78db33b2eb14c7baa19975
|
4
|
+
data.tar.gz: 785f9286455947d79581de9cef5ffc2cde4ecd8b1860f7ab0494c6ae47386ff9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9af7b7e325f515220925b5361cb5c20aefc00add5742539d2b0dfd42a5b9f1d996b880a6d739180ac84d9a8715a68b08325ebcf34008a52a311a9cbe5b51899
|
7
|
+
data.tar.gz: 85ffe608074ddf335004e48dee35feef330bea221de5fdd6f4deab9213df1d266cf29c5edf9d45d07316c588f4d3a62d19e0bd3e7689809cf328375f595a53d2
|
data/README.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# SlippyTilesScorer
|
2
2
|
|
3
|
+
> [!NOTE]
|
4
|
+
> This gem's API is not considered stable yet.
|
5
|
+
> Things might change in the future.
|
6
|
+
|
7
|
+
[![Gem Version](https://badge.fury.io/rb/slippy_tiles_scorer.svg)](https://badge.fury.io/rb/slippy_tiles_scorer) \
|
8
|
+
[![Ruby](https://github.com/simonneutert/slippy_tiles_scorer/actions/workflows/main.yml/badge.svg)](https://github.com/simonneutert/slippy_tiles_scorer/actions/workflows/main.yml)
|
9
|
+
|
3
10
|
Calculate scores of map tiles (x, y) on a map. The scores are total, (max)
|
4
11
|
clusters, and max squares.
|
5
12
|
|
@@ -7,18 +14,16 @@ To experiment with that code, run `bin/console` for an interactive prompt.
|
|
7
14
|
|
8
15
|
## Installation
|
9
16
|
|
10
|
-
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
11
|
-
|
12
17
|
Install the gem and add to the application's Gemfile by executing:
|
13
18
|
|
14
19
|
```bash
|
15
|
-
bundle add
|
20
|
+
bundle add slippy_tiles_scorer
|
16
21
|
```
|
17
22
|
|
18
23
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
19
24
|
|
20
25
|
```bash
|
21
|
-
gem install
|
26
|
+
gem install slippy_tiles_scorer
|
22
27
|
```
|
23
28
|
|
24
29
|
## Usage
|
@@ -43,7 +48,7 @@ collection_of_tiles.add([2, 0])
|
|
43
48
|
collection_of_tiles.add([2, 1])
|
44
49
|
collection_of_tiles.add([2, 2])
|
45
50
|
|
46
|
-
tile_scorer = SlippyTilesScorer::
|
51
|
+
tile_scorer = SlippyTilesScorer::Score.new(tiles_x_y: collection_of_tiles)
|
47
52
|
tile_scorer.valid? # => true
|
48
53
|
|
49
54
|
# the collection_of_tiles is a 3x3 map and will be used to calculate scores,
|
@@ -55,15 +60,17 @@ tile_scorer.visited # => 9
|
|
55
60
|
tile_scorer.clusters # =>
|
56
61
|
# {
|
57
62
|
# :clusters=>[
|
58
|
-
#
|
63
|
+
# [
|
64
|
+
# [0, 0], [1, 0], [0, 1], [1, 1], [0, 2], [1, 2], [2, 2], [2, 1], [2, 0]
|
65
|
+
# ]
|
59
66
|
# ],
|
60
67
|
# :cluster_tiles=>#<Set: {[1, 1]}>,
|
61
|
-
# :clusters_of_cluster_tiles=>[]
|
68
|
+
# :clusters_of_cluster_tiles=>[[[1, 1]]]
|
62
69
|
# }
|
63
70
|
|
64
71
|
# calculate max squares
|
65
|
-
tile_scorer.max_squares # => {:size=>
|
66
|
-
tile_scorer.max_squares(min_size: 4) # => {:size=>
|
72
|
+
tile_scorer.max_squares # => {:size=>0, top_left_tile_x_y=>#<Set: {[0, 0]}>}
|
73
|
+
tile_scorer.max_squares(min_size: 4) # => {:size=>0, top_left_tile_x_y=>#<Set: {}>}
|
67
74
|
```
|
68
75
|
|
69
76
|
### Optimized
|
@@ -72,7 +79,7 @@ An more computationally optimized example of how to use the `TileScorer` class,
|
|
72
79
|
|
73
80
|
```ruby
|
74
81
|
### OPTIMIZE COMPUTATION ###
|
75
|
-
tile_scorer = SlippyTilesScorer::
|
82
|
+
tile_scorer = SlippyTilesScorer::Score.new(tiles_x_y: collection_of_tiles)
|
76
83
|
# Optimize computation by calculating clusters first,
|
77
84
|
result_clusters = tile_scorer.clusters
|
78
85
|
clusters = result_clusters[:clusters]
|
@@ -6,18 +6,17 @@ module SlippyTilesScorer
|
|
6
6
|
attr_accessor :tiles_x_y
|
7
7
|
|
8
8
|
def initialize(tiles_x_y: Set.new)
|
9
|
-
@tiles_x_y =
|
9
|
+
@tiles_x_y = tiles_x_y
|
10
10
|
@cluster_tiles = Set.new
|
11
|
-
@visited =
|
11
|
+
@visited = {}
|
12
12
|
@clusters = []
|
13
13
|
end
|
14
14
|
|
15
15
|
def clusters
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
find_cluster_around(start)
|
16
|
+
@tiles_x_y.each do |i|
|
17
|
+
next if visited?(i[0], i[1])
|
18
|
+
visit!(i[0], i[1])
|
19
|
+
find_cluster_around(i)
|
21
20
|
end
|
22
21
|
{ clusters: @clusters, cluster_tiles: @cluster_tiles }
|
23
22
|
end
|
@@ -25,44 +24,43 @@ module SlippyTilesScorer
|
|
25
24
|
private
|
26
25
|
|
27
26
|
def find_cluster_around(start)
|
28
|
-
cluster =
|
29
|
-
cluster.
|
27
|
+
cluster = []
|
28
|
+
cluster.push(start)
|
30
29
|
todo = [start]
|
30
|
+
broad_search!(todo, cluster)
|
31
31
|
|
32
|
-
cluster
|
33
|
-
|
34
|
-
@clusters.push(cluster) if cluster.size > 1
|
32
|
+
@clusters.push(cluster) if cluster.size > 0
|
35
33
|
cluster
|
36
34
|
end
|
37
35
|
|
38
36
|
def neighbors_up_down_left_right?(neighbors)
|
39
|
-
neighbors.all? { |n| @tiles_x_y.include?(n)
|
37
|
+
neighbors.all? { |n| @tiles_x_y.include?(n) }
|
40
38
|
end
|
41
39
|
|
42
|
-
def broad_search(todo, cluster) # rubocop:disable Metrics/MethodLength
|
40
|
+
def broad_search!(todo, cluster) # rubocop:disable Metrics/MethodLength
|
43
41
|
until todo.empty?
|
44
42
|
point = todo.pop
|
45
43
|
neighbors = neighbor_points(*point)
|
46
|
-
|
47
|
-
next if neighbors.empty?
|
48
|
-
|
49
|
-
@cluster_tiles.add(point) if neighbors_up_down_left_right?(neighbors)
|
44
|
+
neighbors_up_down_left_right?(neighbors) && @cluster_tiles.add(point)
|
50
45
|
neighbors.each do |neighbor|
|
46
|
+
next if visited?(neighbor[0], neighbor[1])
|
51
47
|
next unless @tiles_x_y.include?(neighbor)
|
52
|
-
|
53
|
-
|
54
|
-
@visited.add(neighbor)
|
55
|
-
cluster.add(neighbor)
|
56
|
-
todo.push(neighbor)
|
48
|
+
visit!(*neighbor) && todo.push(neighbor) && cluster.push(neighbor)
|
57
49
|
end
|
58
50
|
end
|
59
|
-
cluster
|
60
51
|
end
|
61
52
|
|
62
|
-
def
|
63
|
-
|
64
|
-
[
|
65
|
-
|
53
|
+
def visit!(x, y)
|
54
|
+
@visited[x] ||= {}
|
55
|
+
@visited[x][y] = true
|
56
|
+
end
|
57
|
+
|
58
|
+
def visited?(x, y)
|
59
|
+
@visited.dig(x, y)
|
60
|
+
end
|
61
|
+
|
62
|
+
def neighbor_points(x, y)
|
63
|
+
[[x - 1, y], [x + 1, y], [x, y + 1], [x, y - 1]]
|
66
64
|
end
|
67
65
|
end
|
68
66
|
end
|
@@ -6,22 +6,33 @@ module SlippyTilesScorer
|
|
6
6
|
attr_accessor :tiles_x_y
|
7
7
|
|
8
8
|
def initialize(tiles_x_y: Set.new)
|
9
|
-
@tiles_x_y =
|
9
|
+
@tiles_x_y = tiles_x_y
|
10
|
+
@tiles_lut = nil
|
10
11
|
end
|
11
12
|
|
12
13
|
# @param min_size [Integer] The minimum size of the square, should be 3 or greater.
|
13
14
|
# As the smallest square is 3x3 and therefor a cluster tile needs to be the center.
|
14
15
|
# @return [Hash] The size of the square and the points of the square.
|
15
16
|
def max_squares(min_size: 3)
|
17
|
+
@max_size_found = 0
|
16
18
|
raise ArgumentError, 'min_size must be 2 or greater' if min_size < 2
|
17
19
|
|
18
|
-
result = { size:
|
20
|
+
result = { size: @max_size_found, top_left_tile_x_y: Set.new }
|
19
21
|
@tiles_x_y.each do |(x, y)|
|
20
22
|
raise ArgumentError, 'x and y must be greater than or equal to 0' if x.negative? || y.negative?
|
21
23
|
|
22
24
|
steps = max_square(x: x, y: y)
|
23
|
-
|
25
|
+
next if steps < min_size
|
26
|
+
if steps > @max_size_found
|
27
|
+
@max_size_found = steps
|
28
|
+
result = { size: @max_size_found, top_left_tile_x_y: Set.new }
|
29
|
+
track_result(result: result, steps: steps, x: x, y: y)
|
30
|
+
elsif steps == @max_size_found
|
31
|
+
result ||= { size: @max_size_found, top_left_tile_x_y: Set.new }
|
32
|
+
track_result(result: result, steps: steps, x: x, y: y)
|
33
|
+
end
|
24
34
|
end
|
35
|
+
@tiles_lut = nil
|
25
36
|
result
|
26
37
|
end
|
27
38
|
|
@@ -32,23 +43,29 @@ module SlippyTilesScorer
|
|
32
43
|
end
|
33
44
|
|
34
45
|
def steps_fulfilled?(x:, y:, steps:) # rubocop:disable Naming/MethodParameterName
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
46
|
+
in_lut?(x: x + steps, y: y + steps) &&
|
47
|
+
(0...steps).all? do |i|
|
48
|
+
in_lut?(x: x + steps, y: y + i) &&
|
49
|
+
in_lut?(x: x + i, y: y + steps)
|
50
|
+
end
|
40
51
|
end
|
41
52
|
|
42
53
|
private
|
43
54
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
def in_lut?(x:, y:)
|
56
|
+
unless @tiles_lut
|
57
|
+
@tiles_lut = {}
|
58
|
+
@tiles_x_y.each do |(x, y)|
|
59
|
+
@tiles_lut[x] ||= {}
|
60
|
+
@tiles_lut[x][y] = true
|
61
|
+
end
|
51
62
|
end
|
63
|
+
@tiles_lut.dig(x, y)
|
64
|
+
end
|
65
|
+
|
66
|
+
def track_result(result:, steps:, x:, y:) # rubocop:disable Naming/MethodParameterName
|
67
|
+
result[:size] = steps
|
68
|
+
result[:top_left_tile_x_y] << [x, y]
|
52
69
|
result
|
53
70
|
end
|
54
71
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slippy_tiles_scorer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Neutert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: For a given set of slippy tiles, this gem calculates the score of the
|
14
14
|
tiles, like total tiles, clusters and max squares.
|