gtfs_stops_clustering 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/gtfs_stops_clustering/data_import.rb +20 -12
- data/lib/gtfs_stops_clustering/dbscan.rb +51 -40
- data/lib/gtfs_stops_clustering/input_consistency_checks.rb +52 -0
- data/lib/gtfs_stops_clustering/redis_geodata.rb +11 -9
- data/lib/gtfs_stops_clustering/version.rb +1 -1
- data/lib/gtfs_stops_clustering.rb +40 -35
- metadata +63 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d10d21f2d65afcf335560f35f8a34e4c8e46b3e6eeb6b7c74d9edf73e3336227
|
4
|
+
data.tar.gz: 67f4f260b43a6ac2f8af21b8c1a5471ee241b3c86f6a8532c55e0554268cdaa0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5ef45bb1402420422984e19918edfe60c5cc73fac8d503be3f605bd83c4b97460a688e79bba16e901cb42ecf358571cc1380467920e2c9b051be08b0fcff5fb
|
7
|
+
data.tar.gz: '0349797d0744abe6432ab20f262ac766118b2a3153b1e5dbb2796d2c3eb359fccc109bdadc17affbe43b9824457701daa5d3a1c434fe43ab40c3c1534dbce382'
|
@@ -1,12 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# lib/data_import.rb
|
2
4
|
|
3
|
-
require
|
4
|
-
require
|
5
|
+
require "csv"
|
6
|
+
require "gtfs"
|
5
7
|
|
8
|
+
# DataImport module
|
6
9
|
module DataImport
|
7
|
-
VERSION='0.0.1'
|
8
10
|
attr_accessor :data_import
|
9
11
|
|
12
|
+
# DataImport class
|
10
13
|
class DataImport
|
11
14
|
attr_accessor :stops, :stops_config_file, :stops_names, :stops_corner_cases, :stops_data, :stops_redis_geodata
|
12
15
|
|
@@ -22,13 +25,13 @@ module DataImport
|
|
22
25
|
end
|
23
26
|
|
24
27
|
def import_stops_corner_cases
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
return unless File.exist?(@stops_config_file)
|
29
|
+
|
30
|
+
CSV.foreach(@stops_config_file, headers: true) do |row|
|
31
|
+
stop_name = row["stop_name"]
|
32
|
+
cluster_name = row["cluster_name"]
|
29
33
|
|
30
|
-
|
31
|
-
end
|
34
|
+
stops_corner_cases << { stop_name: stop_name, cluster_name: cluster_name }
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
@@ -38,13 +41,20 @@ module DataImport
|
|
38
41
|
longitude = row.lon
|
39
42
|
stop_name = row.name
|
40
43
|
|
41
|
-
stop_name =
|
44
|
+
stop_name = stop_name_from_corner_cases(stop_name)
|
42
45
|
|
43
46
|
@stops_names << stop_name
|
44
47
|
@stops_data << [latitude, longitude]
|
45
48
|
@stops_redis_geodata << [longitude, latitude, "#{longitude},#{latitude}"]
|
46
49
|
end
|
47
50
|
end
|
51
|
+
|
52
|
+
def stop_name_from_corner_cases(stop_name)
|
53
|
+
csv_entry = @stops_corner_cases.find do |entry|
|
54
|
+
entry[:stop_name] == stop_name
|
55
|
+
end
|
56
|
+
csv_entry.nil? ? stop_name : csv_entry[:cluster_name]
|
57
|
+
end
|
48
58
|
end
|
49
59
|
|
50
60
|
def import_stops_data(*args)
|
@@ -56,5 +66,3 @@ module DataImport
|
|
56
66
|
}
|
57
67
|
end
|
58
68
|
end
|
59
|
-
|
60
|
-
include DataImport
|
@@ -1,33 +1,47 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require 'text'
|
5
|
-
require 'geocoder'
|
6
|
-
require_relative 'redis_geodata'
|
3
|
+
# lib/gtfs_stops_clustering/dbscan.rb
|
7
4
|
|
5
|
+
require "distance_measures"
|
6
|
+
require "text"
|
7
|
+
require "geocoder"
|
8
|
+
require_relative "redis_geodata"
|
9
|
+
|
10
|
+
# Array class
|
8
11
|
class Array
|
9
|
-
def haversine_distance2(
|
10
|
-
Geocoder::Calculations.distance_between(self,
|
12
|
+
def haversine_distance2(other)
|
13
|
+
Geocoder::Calculations.distance_between(self, other)
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
17
|
+
# DBSCAN module
|
14
18
|
module DBSCAN
|
19
|
+
# Clusterer class
|
15
20
|
class Clusterer
|
21
|
+
include RedisGeodata
|
16
22
|
attr_accessor :points, :options, :clusters
|
17
23
|
|
18
24
|
def initialize(points, stops_redis_geodata, options = {})
|
19
25
|
options[:distance] = :euclidean_distance unless options[:distance]
|
20
26
|
options[:labels] = [] unless options[:labels]
|
21
27
|
|
22
|
-
c = 0
|
23
28
|
redis_geodata_import(stops_redis_geodata, options[:epsilon])
|
24
|
-
@points = points.map { |e| po = Point.new(e, options[:labels][c]); c +=1; po }
|
25
29
|
@options = options
|
26
|
-
|
30
|
+
init_points(points)
|
31
|
+
@clusters = { -1 => [] }
|
27
32
|
|
28
33
|
clusterize!
|
29
34
|
end
|
30
35
|
|
36
|
+
def init_points(points)
|
37
|
+
c = 0
|
38
|
+
@points = points.map do |e|
|
39
|
+
po = Point.new(e, @options[:labels][c])
|
40
|
+
c += 1
|
41
|
+
po
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
31
45
|
def clusterize!
|
32
46
|
current_cluster = -1
|
33
47
|
@points.each do |point|
|
@@ -49,10 +63,10 @@ module DBSCAN
|
|
49
63
|
# Get Cluster Position
|
50
64
|
cluster_pos = find_cluster_position(clusters[current_cluster])
|
51
65
|
|
52
|
-
clusters[current_cluster].each
|
66
|
+
clusters[current_cluster].each do |e|
|
53
67
|
e.cluster_name = cluster_name
|
54
68
|
e.cluster_pos = cluster_pos
|
55
|
-
|
69
|
+
end
|
56
70
|
else
|
57
71
|
clusters[-1].push(point)
|
58
72
|
end
|
@@ -91,9 +105,11 @@ module DBSCAN
|
|
91
105
|
neighbors = []
|
92
106
|
geosearch_results = geosearch(point.items[1], point.items[0])
|
93
107
|
geosearch_results.each do |neighbor_pos|
|
94
|
-
coordinates = neighbor_pos.split(
|
95
|
-
neighbor = @points.find
|
96
|
-
|
108
|
+
coordinates = neighbor_pos.split(",")
|
109
|
+
neighbor = @points.find do |elem|
|
110
|
+
elem.items[0] == coordinates[1] &&
|
111
|
+
elem.items[1] == coordinates[0]
|
112
|
+
end
|
97
113
|
next unless neighbor
|
98
114
|
|
99
115
|
string_distance = Text::Levenshtein.distance(point.label.downcase, neighbor.label.downcase)
|
@@ -112,9 +128,7 @@ module DBSCAN
|
|
112
128
|
|
113
129
|
if new_points.size >= options[:min_points]
|
114
130
|
new_points.each do |p|
|
115
|
-
unless neighbors.include?(p)
|
116
|
-
neighbors.push(p)
|
117
|
-
end
|
131
|
+
neighbors.push(p) unless neighbors.include?(p)
|
118
132
|
end
|
119
133
|
end
|
120
134
|
end
|
@@ -127,32 +141,31 @@ module DBSCAN
|
|
127
141
|
|
128
142
|
cluster_points
|
129
143
|
end
|
130
|
-
end
|
131
144
|
|
132
|
-
|
133
|
-
|
134
|
-
|
145
|
+
def find_cluster_name(labels)
|
146
|
+
words = labels.map { |label| label.strip.split }
|
147
|
+
common_title = ""
|
135
148
|
|
136
|
-
|
137
|
-
|
138
|
-
|
149
|
+
# Loop through each word index starting from the first
|
150
|
+
(0...words.first.length).each do |i|
|
151
|
+
words_at_index = words.map { |word_list| word_list[i] }
|
139
152
|
|
140
|
-
|
153
|
+
break unless words_at_index.uniq.length == 1
|
141
154
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
common_title.strip! ? common_title : labels.first
|
146
|
-
end
|
155
|
+
common_title += " #{words_at_index.first.capitalize}"
|
156
|
+
end
|
147
157
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
158
|
+
common_title.strip ? common_title : labels.first
|
159
|
+
end
|
160
|
+
def find_cluster_position(cluster)
|
161
|
+
total_lat = cluster.map { |e| e.items[0].to_f }.sum
|
162
|
+
total_lon = cluster.map { |e| e.items[1].to_f }.sum
|
163
|
+
avg_lat = total_lat / cluster.size
|
164
|
+
avg_lon = total_lon / cluster.size
|
165
|
+
[avg_lat, avg_lon]
|
166
|
+
end
|
154
167
|
end
|
155
|
-
|
168
|
+
# Point class
|
156
169
|
class Point
|
157
170
|
attr_accessor :items, :cluster, :visited, :label, :cluster_name, :cluster_pos
|
158
171
|
|
@@ -176,5 +189,3 @@ module DBSCAN
|
|
176
189
|
clusterer.labeled_results
|
177
190
|
end
|
178
191
|
end
|
179
|
-
|
180
|
-
include DBSCAN
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/input_consistency_checks.rb
|
4
|
+
|
5
|
+
# InputConsistencyChecks module
|
6
|
+
module InputConsistencyChecks
|
7
|
+
# InputConsistencyChecks class
|
8
|
+
class InputConsistencyChecks
|
9
|
+
attr_accessor :gtfs_paths, :epsilon, :min_points, :names_similarity, :stops_config_path
|
10
|
+
|
11
|
+
def initialize(gtfs_paths, epsilon, min_points, names_similarity, stops_config_path)
|
12
|
+
@gtfs_paths = gtfs_paths
|
13
|
+
@stops_config_path = stops_config_path
|
14
|
+
@epsilon = epsilon
|
15
|
+
@min_points = min_points
|
16
|
+
@names_similarity = names_similarity
|
17
|
+
input_consistency_checks
|
18
|
+
end
|
19
|
+
|
20
|
+
def input_consistency_checks
|
21
|
+
gtfs_paths_check
|
22
|
+
epsilon_check
|
23
|
+
min_points_check
|
24
|
+
names_similarity_check
|
25
|
+
end
|
26
|
+
|
27
|
+
def gtfs_paths_check
|
28
|
+
raise ArgumentError, "gtfs_paths cannot be nil" if @gtfs_paths.nil?
|
29
|
+
raise ArgumentError, "gtfs_paths must be an Array" unless @gtfs_paths.is_a?(Array)
|
30
|
+
raise ArgumentError, "gtfs_paths must not be empty" if @gtfs_paths.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
def epsilon_check
|
34
|
+
raise ArgumentError, "epsilon must be a Float" unless @epsilon.is_a?(Float)
|
35
|
+
raise ArgumentError, "epsilon must be greater than 0" if @epsilon.negative?
|
36
|
+
end
|
37
|
+
|
38
|
+
def min_points_check
|
39
|
+
raise ArgumentError, "min_points must be an Integer" unless @min_points.is_a?(Integer)
|
40
|
+
raise ArgumentError, "min_points must be greater than 0" if @min_points.negative?
|
41
|
+
end
|
42
|
+
|
43
|
+
def names_similarity_check
|
44
|
+
raise ArgumentError, "names_similarity must be a Float" unless @names_similarity.is_a?(Float)
|
45
|
+
raise ArgumentError, "names_similarity must be between 0 and 1" if @names_similarity.negative? || @names_similarity > 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def input_consistency_checks(gtfs_paths, epsilon, min_points, names_similarity, stop_config_path)
|
50
|
+
@input_consistency_checks = InputConsistencyChecks.new(gtfs_paths, epsilon, min_points, names_similarity, stop_config_path)
|
51
|
+
end
|
52
|
+
end
|
@@ -1,17 +1,21 @@
|
|
1
|
-
#
|
2
|
-
require 'redis'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
3
|
+
# lib/gtfs_stops_clustering/redis_geodata.rb
|
4
|
+
|
5
|
+
require "redis"
|
6
|
+
|
7
|
+
# RedisGeodata module
|
4
8
|
module RedisGeodata
|
5
|
-
VERSION='0.0.1'
|
6
9
|
attr_accessor :redis
|
7
10
|
|
11
|
+
# RedisGeodata class
|
8
12
|
class RedisGeodata
|
9
13
|
attr_accessor :stops, :key, :redis, :epsilon
|
10
14
|
|
11
15
|
def initialize(stops, epsilon)
|
12
|
-
@redis = Redis.new(url:
|
16
|
+
@redis = Redis.new(url: "redis://127.0.0.1:6379")
|
13
17
|
@stops = stops
|
14
|
-
@key =
|
18
|
+
@key = "stops"
|
15
19
|
@epsilon = epsilon
|
16
20
|
geoadd
|
17
21
|
end
|
@@ -22,8 +26,8 @@ module RedisGeodata
|
|
22
26
|
end
|
23
27
|
|
24
28
|
def geosearch(longitude, latitude)
|
25
|
-
list = @redis.georadius(@key, longitude, latitude, @epsilon,
|
26
|
-
list.reject! { |point| point == longitude
|
29
|
+
list = @redis.georadius(@key, longitude, latitude, @epsilon, "km")
|
30
|
+
list.reject! { |point| point == "#{longitude},#{latitude}" }
|
27
31
|
list
|
28
32
|
end
|
29
33
|
end
|
@@ -36,5 +40,3 @@ module RedisGeodata
|
|
36
40
|
@redis.geosearch(*args)
|
37
41
|
end
|
38
42
|
end
|
39
|
-
|
40
|
-
include RedisGeodata
|
@@ -1,28 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# lib/gtfs_stops_clustering.rb
|
2
4
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require_relative
|
6
|
-
|
5
|
+
require "rubygems"
|
6
|
+
require "bundler/setup"
|
7
|
+
require_relative "gtfs_stops_clustering/version"
|
8
|
+
require "gtfs"
|
9
|
+
require "csv"
|
10
|
+
require_relative "./gtfs_stops_clustering/data_import"
|
11
|
+
require_relative "./gtfs_stops_clustering/dbscan"
|
12
|
+
require_relative "./gtfs_stops_clustering/input_consistency_checks"
|
7
13
|
|
14
|
+
# GtfsStopClustering module
|
8
15
|
module GtfsStopsClustering
|
9
|
-
VERSION='0.0.1'
|
10
16
|
attr_accessor :gtfs_stops_clustering
|
11
17
|
|
18
|
+
# GtfsStopsClustering class
|
12
19
|
class GtfsStopsClustering
|
13
|
-
|
20
|
+
include InputConsistencyChecks
|
21
|
+
include DataImport
|
22
|
+
include DBSCAN
|
23
|
+
attr_accessor :clusters, :gtfs_paths, :gtfs_stops, :stops_config_path, :epsilon, :min_points, :names_similarity
|
14
24
|
|
15
|
-
def initialize(
|
25
|
+
def initialize(gtfs_paths, epsilon, min_points, names_similarity, stops_config_path)
|
26
|
+
@gtfs_paths = gtfs_paths
|
27
|
+
@stops_config_path = stops_config_path
|
28
|
+
@epsilon = epsilon
|
29
|
+
@min_points = min_points
|
30
|
+
@names_similarity = names_similarity
|
31
|
+
input_consistency_checks(@gtfs_paths, @epsilon, @min_points, @names_similarity, @stops_config_path)
|
16
32
|
@clusters = []
|
17
|
-
|
18
|
-
|
19
|
-
@stops_config_path = stops_config_path
|
20
|
-
@epsilon = epsilon
|
21
|
-
@min_points = min_points
|
22
|
-
@names_similarity = names_similarity
|
23
|
-
@gtfs_stops = create_stops_merged
|
24
|
-
clusterize_stops_csv(@gtfs_stops)
|
25
|
-
end
|
33
|
+
@gtfs_stops = create_stops_merged
|
34
|
+
clusterize_stops
|
26
35
|
end
|
27
36
|
|
28
37
|
def create_stops_merged
|
@@ -34,11 +43,20 @@ module GtfsStopsClustering
|
|
34
43
|
gtfs_stops.flatten
|
35
44
|
end
|
36
45
|
|
37
|
-
def
|
38
|
-
data = import_stops_data(
|
39
|
-
@clusters = DBSCAN(
|
46
|
+
def clusterize_stops
|
47
|
+
data = import_stops_data(@gtfs_stops, @stops_config_path)
|
48
|
+
@clusters = DBSCAN(data[:stops_data],
|
49
|
+
data[:stops_redis_geodata],
|
50
|
+
epsilon: @epsilon,
|
51
|
+
min_points: @min_points,
|
52
|
+
similarity: @names_similarity,
|
53
|
+
distance: :haversine_distance2,
|
54
|
+
labels: data[:stops_names])
|
55
|
+
map_clustered_stops
|
56
|
+
end
|
40
57
|
|
41
|
-
|
58
|
+
def map_clustered_stops
|
59
|
+
@clusters.each_value do |cluster|
|
42
60
|
cluster.each do |stop|
|
43
61
|
gtfs_stop = @gtfs_stops.find { |e| e.lat == stop[:stop_lat] && e.lon == stop[:stop_lon] }
|
44
62
|
stop[:stop_id] = gtfs_stop.id
|
@@ -46,24 +64,11 @@ module GtfsStopsClustering
|
|
46
64
|
stop[:parent_station] = gtfs_stop.parent_station
|
47
65
|
end
|
48
66
|
end
|
49
|
-
|
50
|
-
output_path = 'stop_clusters.txt'
|
51
|
-
File.open(output_path, 'w') do |file|
|
52
|
-
@clusters.each do |cluster_id, cluster |
|
53
|
-
file.puts "Cluster #{cluster_id}"
|
54
|
-
cluster.each do |point|
|
55
|
-
file.puts point.inspect
|
56
|
-
end
|
57
|
-
file.puts
|
58
|
-
end
|
59
|
-
end
|
60
67
|
end
|
61
68
|
end
|
62
69
|
|
63
|
-
def
|
64
|
-
@gtfs_stops_clustering = GtfsStopsClustering.new(
|
70
|
+
def build_clusters(gtfs_paths, epsilon, min_points, names_similarity = 1, stop_config_path = "")
|
71
|
+
@gtfs_stops_clustering = GtfsStopsClustering.new(gtfs_paths, epsilon, min_points, names_similarity, stop_config_path)
|
65
72
|
@gtfs_stops_clustering.clusters
|
66
73
|
end
|
67
74
|
end
|
68
|
-
|
69
|
-
include GtfsStopsClustering
|
metadata
CHANGED
@@ -1,49 +1,49 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gtfs_stops_clustering
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Pietro Visconti
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-12-
|
11
|
+
date: 2023-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: csv
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '3.2'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.2.8
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
29
|
+
version: '3.2'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.2.8
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
34
|
+
name: distance_measures
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
37
|
- - "~>"
|
32
38
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
- - ">="
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: 1.3.1
|
39
|
+
version: 0.0.6
|
37
40
|
type: :runtime
|
38
41
|
prerelease: false
|
39
42
|
version_requirements: !ruby/object:Gem::Requirement
|
40
43
|
requirements:
|
41
44
|
- - "~>"
|
42
45
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: 1.3.1
|
46
|
+
version: 0.0.6
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: geocoder
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -65,25 +65,19 @@ dependencies:
|
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: 1.8.2
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
|
-
name:
|
68
|
+
name: gtfs
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
70
70
|
requirements:
|
71
71
|
- - "~>"
|
72
72
|
- !ruby/object:Gem::Version
|
73
|
-
version:
|
74
|
-
- - ">="
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
version: 3.2.8
|
73
|
+
version: 0.4.1
|
77
74
|
type: :runtime
|
78
75
|
prerelease: false
|
79
76
|
version_requirements: !ruby/object:Gem::Requirement
|
80
77
|
requirements:
|
81
78
|
- - "~>"
|
82
79
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
84
|
-
- - ">="
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
version: 3.2.8
|
80
|
+
version: 0.4.1
|
87
81
|
- !ruby/object:Gem::Dependency
|
88
82
|
name: redis
|
89
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,23 +99,57 @@ dependencies:
|
|
105
99
|
- !ruby/object:Gem::Version
|
106
100
|
version: 5.0.8
|
107
101
|
- !ruby/object:Gem::Dependency
|
108
|
-
name:
|
102
|
+
name: text
|
109
103
|
requirement: !ruby/object:Gem::Requirement
|
110
104
|
requirements:
|
111
105
|
- - "~>"
|
112
106
|
- !ruby/object:Gem::Version
|
113
|
-
version:
|
107
|
+
version: '1.3'
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.3.1
|
114
111
|
type: :runtime
|
115
112
|
prerelease: false
|
116
113
|
version_requirements: !ruby/object:Gem::Requirement
|
117
114
|
requirements:
|
118
115
|
- - "~>"
|
119
116
|
- !ruby/object:Gem::Version
|
120
|
-
version:
|
117
|
+
version: '1.3'
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 1.3.1
|
121
|
+
- !ruby/object:Gem::Dependency
|
122
|
+
name: minitest
|
123
|
+
requirement: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - "~>"
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '5.20'
|
128
|
+
type: :development
|
129
|
+
prerelease: false
|
130
|
+
version_requirements: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - "~>"
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '5.20'
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: pry
|
137
|
+
requirement: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - "~>"
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 0.14.2
|
142
|
+
type: :development
|
143
|
+
prerelease: false
|
144
|
+
version_requirements: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - "~>"
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 0.14.2
|
121
149
|
description: A gem to read GTFS stops data and create clusters based on coordinates
|
122
150
|
and stop names' similarities.
|
123
151
|
email:
|
124
|
-
-
|
152
|
+
- pietro.visconti2001@gmail.com
|
125
153
|
executables: []
|
126
154
|
extensions: []
|
127
155
|
extra_rdoc_files: []
|
@@ -129,12 +157,16 @@ files:
|
|
129
157
|
- lib/gtfs_stops_clustering.rb
|
130
158
|
- lib/gtfs_stops_clustering/data_import.rb
|
131
159
|
- lib/gtfs_stops_clustering/dbscan.rb
|
160
|
+
- lib/gtfs_stops_clustering/input_consistency_checks.rb
|
132
161
|
- lib/gtfs_stops_clustering/redis_geodata.rb
|
133
162
|
- lib/gtfs_stops_clustering/version.rb
|
134
|
-
homepage:
|
163
|
+
homepage: https://github.com/Visco01/gtfs_stops_clustering
|
135
164
|
licenses:
|
136
165
|
- MIT
|
137
|
-
metadata:
|
166
|
+
metadata:
|
167
|
+
homepage_uri: https://github.com/Visco01/gtfs_stops_clustering
|
168
|
+
source_code_uri: https://github.com/Visco01/gtfs_stops_clustering
|
169
|
+
changelog_uri: https://github.com/Visco01/gtfs_stops_clustering/blob/main/CHANGELOG.md
|
138
170
|
post_install_message:
|
139
171
|
rdoc_options: []
|
140
172
|
require_paths:
|
@@ -150,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
182
|
- !ruby/object:Gem::Version
|
151
183
|
version: '0'
|
152
184
|
requirements: []
|
153
|
-
rubygems_version: 3.4.
|
185
|
+
rubygems_version: 3.4.22
|
154
186
|
signing_key:
|
155
187
|
specification_version: 4
|
156
188
|
summary: A gem to read GTFS stops data and create clusters based on coordinates and
|