ninoxe 0.0.8

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.
Files changed (93) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +49 -0
  4. data/app/assets/javascripts/ninoxe/application.js +15 -0
  5. data/app/assets/stylesheets/ninoxe/application.css +13 -0
  6. data/app/controllers/ninoxe/application_controller.rb +4 -0
  7. data/app/helpers/ninoxe/application_helper.rb +4 -0
  8. data/app/models/chouette/access_link.rb +63 -0
  9. data/app/models/chouette/access_point.rb +145 -0
  10. data/app/models/chouette/access_point_type.rb +50 -0
  11. data/app/models/chouette/active_record.rb +66 -0
  12. data/app/models/chouette/area_type.rb +56 -0
  13. data/app/models/chouette/chouette_structure.dump +3417 -0
  14. data/app/models/chouette/command.rb +93 -0
  15. data/app/models/chouette/command_line_support.rb +35 -0
  16. data/app/models/chouette/company.rb +19 -0
  17. data/app/models/chouette/connection_link.rb +43 -0
  18. data/app/models/chouette/connection_link_type.rb +51 -0
  19. data/app/models/chouette/direction.rb +60 -0
  20. data/app/models/chouette/exporter.rb +32 -0
  21. data/app/models/chouette/file_validator.rb +47 -0
  22. data/app/models/chouette/group_of_line.rb +30 -0
  23. data/app/models/chouette/journey_pattern.rb +63 -0
  24. data/app/models/chouette/line.rb +65 -0
  25. data/app/models/chouette/link_orientation_type.rb +49 -0
  26. data/app/models/chouette/loader.rb +110 -0
  27. data/app/models/chouette/network.rb +33 -0
  28. data/app/models/chouette/object_id.rb +36 -0
  29. data/app/models/chouette/pt_link.rb +39 -0
  30. data/app/models/chouette/route.rb +158 -0
  31. data/app/models/chouette/stop_area.rb +273 -0
  32. data/app/models/chouette/stop_point.rb +33 -0
  33. data/app/models/chouette/time_table.rb +146 -0
  34. data/app/models/chouette/time_table_date.rb +14 -0
  35. data/app/models/chouette/time_table_period.rb +26 -0
  36. data/app/models/chouette/time_table_vehicle_journey.rb +5 -0
  37. data/app/models/chouette/transport_mode.rb +71 -0
  38. data/app/models/chouette/trident_active_record.rb +97 -0
  39. data/app/models/chouette/vehicle_journey.rb +101 -0
  40. data/app/models/chouette/vehicle_journey_at_stop.rb +45 -0
  41. data/app/models/chouette/wayback.rb +50 -0
  42. data/app/views/layouts/ninoxe/application.html.erb +14 -0
  43. data/config/database.yml +9 -0
  44. data/config/database.yml.ci +14 -0
  45. data/config/database.yml.travis +9 -0
  46. data/config/locales/en.yml +15 -0
  47. data/config/locales/fr.yml +16 -0
  48. data/config/routes.rb +2 -0
  49. data/db/migrate/20120213131553_create_chouette_line.rb +26 -0
  50. data/db/migrate/20120214101458_create_chouette_company.rb +25 -0
  51. data/db/migrate/20120214101645_create_chouette_ptnetwork.rb +24 -0
  52. data/db/migrate/20120406144221_create_chouette_stop_area.rb +33 -0
  53. data/db/migrate/20120411144209_create_time_table.rb +38 -0
  54. data/db/migrate/20120425064403_create_chouette_route.rb +22 -0
  55. data/db/migrate/20120425123944_create_chouette_stop_point.rb +17 -0
  56. data/db/migrate/20120426114527_create_chouette_connection_link.rb +28 -0
  57. data/db/migrate/20120521073709_create_chouette_journey_pattern.rb +26 -0
  58. data/db/migrate/20120521073723_create_chouette_journey_pattern_stop_point.rb +14 -0
  59. data/db/migrate/20120521073740_create_chouette_time_slot.rb +22 -0
  60. data/db/migrate/20120521073746_create_chouette_vehicle_journey.rb +34 -0
  61. data/db/migrate/20120521073758_create_chouette_vehicle_journey_at_stop.rb +25 -0
  62. data/db/migrate/20120521073900_create_chouette_time_table_vehicle_journey.rb +16 -0
  63. data/db/migrate/20120521132304_create_chouette_access_point.rb +34 -0
  64. data/db/migrate/20120521132313_create_chouette_access_link.rb +33 -0
  65. data/db/migrate/20120521132429_create_chouette_facility.rb +34 -0
  66. data/db/migrate/20120521132502_create_chouette_facility_feature.rb +12 -0
  67. data/db/migrate/20120521132551_create_chouette_group_of_line.rb +18 -0
  68. data/db/migrate/20120521132600_create_chouette_group_of_line_line.rb +12 -0
  69. data/db/migrate/20120521132656_create_chouette_routing_constrains_line.rb +12 -0
  70. data/db/migrate/20120521132724_create_chouette_stoparea_stoparea.rb +12 -0
  71. data/db/migrate/20120531091529_create_chouette_pt_link.rb +21 -0
  72. data/db/migrate/20120926141405_add_id_to_time_table_date.rb +12 -0
  73. data/db/migrate/20120926141415_add_id_to_time_table_period.rb +12 -0
  74. data/db/migrate/20121024072219_add_fields_to_access_points.rb +12 -0
  75. data/lib/chouette_factories.rb +1 -0
  76. data/lib/factories/chouette_access_links.rb +11 -0
  77. data/lib/factories/chouette_access_points.rb +8 -0
  78. data/lib/factories/chouette_companies.rb +5 -0
  79. data/lib/factories/chouette_connection_links.rb +11 -0
  80. data/lib/factories/chouette_group_of_lines.rb +4 -0
  81. data/lib/factories/chouette_journey_pattern.rb +32 -0
  82. data/lib/factories/chouette_lines.rb +20 -0
  83. data/lib/factories/chouette_networks.rb +5 -0
  84. data/lib/factories/chouette_routes.rb +18 -0
  85. data/lib/factories/chouette_stop_areas.rb +8 -0
  86. data/lib/factories/chouette_stop_points.rb +7 -0
  87. data/lib/factories/chouette_time_table.rb +21 -0
  88. data/lib/factories/chouette_vehicle_journey.rb +50 -0
  89. data/lib/factories/chouette_vehicle_journey_at_stop.rb +5 -0
  90. data/lib/ninoxe/engine.rb +15 -0
  91. data/lib/ninoxe/version.rb +3 -0
  92. data/lib/ninoxe.rb +7 -0
  93. metadata +251 -0
@@ -0,0 +1,110 @@
1
+ class Chouette::Loader
2
+
3
+ attr_reader :schema, :database, :user, :password, :host
4
+
5
+ def initialize(schema)
6
+ @schema = schema
7
+
8
+ Chouette::ActiveRecord.connection_pool.spec.config.tap do |config|
9
+ @database = config[:database]
10
+ @user = config[:username]
11
+ @password = config[:password]
12
+ @host = (config[:host] or "localhost")
13
+ end
14
+ end
15
+
16
+ # Load dump where datas are in schema 'chouette'
17
+ def load_dump(file)
18
+ logger.info "Load #{file} in schema #{schema}"
19
+ with_pg_password do
20
+ execute!("sed -e 's/ chouette/ \"#{schema}\"/' -e 's/ OWNER TO .*;/ OWNER TO #{user};/' #{file} | psql #{pg_options} --set ON_ERROR_ROLLBACK=1 --set ON_ERROR_STOP=1")
21
+ end
22
+ self
23
+ end
24
+
25
+ def self.chouette_command=(command)
26
+ Chouette::Command.command = command
27
+ end
28
+
29
+ class << self
30
+ deprecate :chouette_command= => "Use Chouette::Command.command ="
31
+ end
32
+
33
+ def chouette_command
34
+ @chouette_command ||= Chouette::Command.new(:schema => schema)
35
+ end
36
+
37
+ def import(file, options = {})
38
+ options = {
39
+ :format => :neptune
40
+ }.merge(options)
41
+
42
+ command_options = {
43
+ :c => "import",
44
+ :o => "line",
45
+ :format => options.delete(:format).to_s.upcase,
46
+ :input_file => File.expand_path(file),
47
+ :optimize_memory => true
48
+ }.merge(options)
49
+
50
+ logger.info "Import #{file} in schema #{schema}"
51
+ chouette_command.run! command_options
52
+ end
53
+
54
+ def backup(file)
55
+ logger.info "Backup schema #{schema} in #{file}"
56
+
57
+ with_pg_password do
58
+ execute!("pg_dump -n #{schema} -f #{file} #{pg_options}")
59
+ end
60
+
61
+ self
62
+ end
63
+
64
+ def pg_options
65
+ [].tap do |options|
66
+ options << "-U #{user}" if user
67
+ options << "-h #{host}" if host
68
+ options << database
69
+ end.join(" ")
70
+ end
71
+
72
+ def create
73
+ logger.info "Create schema #{schema}"
74
+ with_pg_password do
75
+ execute!("psql -c 'CREATE SCHEMA \"#{schema}\";' #{pg_options}")
76
+ end
77
+ self
78
+ end
79
+
80
+ def drop
81
+ logger.info "Drop schema #{schema}"
82
+ with_pg_password do
83
+ execute!("psql -c 'DROP SCHEMA \"#{schema}\" CASCADE;' #{pg_options}")
84
+ end
85
+ self
86
+ end
87
+
88
+ def with_pg_password(&block)
89
+ ENV['PGPASSWORD'] = password.to_s if password
90
+ begin
91
+ yield
92
+ ensure
93
+ ENV['PGPASSWORD'] = nil
94
+ end
95
+ end
96
+
97
+ @@binarisation_command = "binarisation"
98
+ cattr_accessor :binarisation_command
99
+
100
+ def binarize(period, target_directory)
101
+ # TODO check these computed daybefore/dayafter
102
+ day_before = Date.today - period.begin
103
+ day_after = period.end - period.begin
104
+
105
+ execute! "#{binarisation_command} --host=#{host} --dbname=#{database} --user=#{user} --password=#{password} --schema=#{schema} --daybefore=#{day_before} --dayafter=#{day_after} --targetdirectory=#{target_directory}"
106
+ end
107
+
108
+ include Chouette::CommandLineSupport
109
+
110
+ end
@@ -0,0 +1,33 @@
1
+ class Chouette::Network < Chouette::TridentActiveRecord
2
+ # FIXME http://jira.codehaus.org/browse/JRUBY-6358
3
+ set_primary_key :id
4
+
5
+ has_many :lines
6
+
7
+ validates_presence_of :registration_number
8
+ validates_uniqueness_of :registration_number
9
+ validates_format_of :registration_number, :with => %r{\A[0-9A-Za-z_-]+\Z}
10
+
11
+ validates_presence_of :name
12
+
13
+ attr_accessible :objectid, :object_version, :creation_time, :creator_id, :version_date, :description, :name
14
+ attr_accessible :registration_number, :source_name, :source_type, :source_identifier, :comment
15
+
16
+ def self.object_id_key
17
+ "GroupOfLine"
18
+ end
19
+
20
+ def self.nullable_attributes
21
+ [:source_name, :source_type, :source_identifier, :comment]
22
+ end
23
+
24
+ def commercial_stop_areas
25
+ Chouette::StopArea.joins(:children => [:stop_points => [:route => [:line => :network] ] ]).where(:networks => {:id => self.id}).uniq
26
+ end
27
+
28
+ def stop_areas
29
+ Chouette::StopArea.joins(:stop_points => [:route => [:line => :network] ]).where(:networks => {:id => self.id})
30
+ end
31
+
32
+ end
33
+
@@ -0,0 +1,36 @@
1
+ class Chouette::ObjectId < String
2
+
3
+ def valid?
4
+ parts.present?
5
+ end
6
+ alias_method :objectid?, :valid?
7
+
8
+ @@format = /^([0-9A-Za-z_]+):([A-Za-z]+):([0-9A-Za-z_-]+)$/
9
+ cattr_reader :format
10
+
11
+ def parts
12
+ match(format).try(:captures)
13
+ end
14
+
15
+ def system_id
16
+ parts.try(:first)
17
+ end
18
+
19
+ def object_type
20
+ parts.try(:second)
21
+ end
22
+
23
+ def local_id
24
+ parts.try(:third)
25
+ end
26
+
27
+ def self.create(system_id, object_type, local_id)
28
+ new [system_id, object_type, local_id].join(":")
29
+ end
30
+
31
+ def self.new(string)
32
+ string ||= ""
33
+ self === string ? string : super
34
+ end
35
+
36
+ end
@@ -0,0 +1,39 @@
1
+ require 'geokit'
2
+
3
+ class Chouette::PtLink < Chouette::ActiveRecord
4
+ # FIXME http://jira.codehaus.org/browse/JRUBY-6358
5
+ set_primary_key :id
6
+
7
+ attr_accessible :start_of_link_id, :end_of_link_id, :route_id, :objectid, :object_version, :creation_time, :creator_id, :name, :comment, :link_distance
8
+ include Geokit::Mappable
9
+
10
+
11
+ def geometry
12
+ the_geom
13
+ end
14
+
15
+ def self.import_csv
16
+ csv_file = Rails.root + "chouette_pt_links.csv"
17
+ if File.exists?( csv_file)
18
+ csv = CSV::Reader.parse(File.read(csv_file))
19
+
20
+ slug = csv.shift.first
21
+
22
+ Network::Base.find_by_slug( slug).tune_connection
23
+
24
+ csv.each do |row|
25
+ origin = Chouette::StopArea.find_by_objectid( row[0])
26
+ destination = Chouette::StopArea.find_by_objectid( row[1])
27
+
28
+ raise "unknown origin #{row[0]}" unless origin
29
+ raise "unknown destination #{row[1]}" unless destination
30
+
31
+ Chouette::PtLink.create( :departure_id => origin.id,
32
+ :arrival_id => destination.id,
33
+ :the_geom => GeoRuby::SimpleFeatures::Geometry.from_hex_ewkb( row[2]))
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,158 @@
1
+ class Chouette::Route < Chouette::TridentActiveRecord
2
+ # FIXME http://jira.codehaus.org/browse/JRUBY-6358
3
+ set_primary_key :id
4
+
5
+ attr_accessor :wayback_code
6
+ attr_accessor :direction_code
7
+
8
+ attr_accessible :direction_code, :wayback_code, :line_id, :objectid, :object_version, :creation_time, :creator_id, :name
9
+ attr_accessible :comment, :opposite_route_id, :published_name, :number, :direction, :wayback
10
+
11
+ def self.nullable_attributes
12
+ [:published_name, :comment, :number]
13
+ end
14
+
15
+ belongs_to :line
16
+
17
+ has_many :journey_patterns, :dependent => :destroy
18
+ has_many :vehicle_journeys, :dependent => :destroy do
19
+ def timeless
20
+ all( :conditions => ['vehicle_journeys.id NOT IN (?)', Chouette::VehicleJourneyAtStop.where( :stop_point_id => proxy_association.owner.journey_patterns.pluck( :departure_stop_point_id)).pluck(:vehicle_journey_id)] )
21
+ end
22
+ end
23
+ belongs_to :opposite_route, :class_name => 'Chouette::Route', :foreign_key => :opposite_route_id
24
+ has_many :stop_points, :order => 'position', :dependent => :destroy do
25
+ def find_by_stop_area(stop_area)
26
+ stop_area_ids = Integer === stop_area ? [stop_area] : (stop_area.children_in_depth + [stop_area]).map(&:id)
27
+ where( :stop_area_id => stop_area_ids).first or
28
+ raise ActiveRecord::RecordNotFound.new("Can't find a StopArea #{stop_area.inspect} in Route #{proxy_owner.id.inspect}'s StopPoints")
29
+ end
30
+
31
+ def between(departure, arrival)
32
+ between_positions = [departure, arrival].collect do |endpoint|
33
+ case endpoint
34
+ when Chouette::StopArea
35
+ find_by_stop_area(endpoint).position
36
+ when Chouette::StopPoint
37
+ endpoint.position
38
+ when Integer
39
+ endpoint
40
+ else
41
+ raise ActiveRecord::RecordNotFound.new("Can't determine position in route #{proxy_owner.id} with #{departure.inspect}")
42
+ end
43
+ end
44
+ where(" position between ? and ? ", between_positions.first, between_positions.last)
45
+ end
46
+ end
47
+ has_many :stop_areas, :through => :stop_points, :order => 'stop_points.position' do
48
+ def between(departure, arrival)
49
+ departure, arrival = [departure, arrival].collect do |endpoint|
50
+ String === endpoint ? Chouette::StopArea.find_by_objectid(endpoint) : endpoint
51
+ end
52
+ proxy_owner.stop_points.between(departure, arrival).includes(:stop_area).collect(&:stop_area)
53
+ end
54
+ end
55
+
56
+ validates_presence_of :name
57
+ validates_presence_of :line
58
+ validates_presence_of :direction_code
59
+ validates_presence_of :wayback_code
60
+
61
+ before_destroy :dereference_opposite_route
62
+
63
+ def dereference_opposite_route
64
+ self.line.routes.each do |r|
65
+ r.update_attributes( :opposite_route => nil) if r.opposite_route == self
66
+ end
67
+ end
68
+
69
+ def geometry
70
+ points = stop_areas.map(&:to_lat_lng).compact.map do |loc|
71
+ [loc.lng, loc.lat]
72
+ end
73
+ GeoRuby::SimpleFeatures::LineString.from_coordinates( points, 4326)
74
+ end
75
+
76
+ def time_tables
77
+ self.vehicle_journeys.joins(:time_tables).map(&:"time_tables").flatten.uniq
78
+ end
79
+
80
+ def sorted_vehicle_journeys
81
+ vehicle_journeys.includes( :vehicle_journey_at_stops, :journey_pattern).where( "vehicle_journey_at_stops.stop_point_id=journey_patterns.departure_stop_point_id").order( "vehicle_journey_at_stops.departure_time")
82
+ end
83
+
84
+ def self.direction_binding
85
+ { "A" => "straight_forward",
86
+ "R" => "backward",
87
+ "ClockWise" => "clock_wise",
88
+ "CounterClockWise" => "counter_clock_wise",
89
+ "North" => "north",
90
+ "NorthWest" => "north_west",
91
+ "West" => "west",
92
+ "SouthWest" => "south_west",
93
+ "South" => "south",
94
+ "SouthEast" => "south_east",
95
+ "East" => "east",
96
+ "NorthEast" => "north_east"}
97
+ end
98
+ def direction_code
99
+ return nil if self.class.direction_binding[direction].nil?
100
+ Chouette::Direction.new( self.class.direction_binding[direction])
101
+ end
102
+ def direction_code=(direction_code)
103
+ self.direction = nil
104
+ self.class.direction_binding.each do |k,v|
105
+ self.direction = k if v==direction_code
106
+ end
107
+ end
108
+ @@directions = nil
109
+ def self.directions
110
+ @@directions ||= Chouette::Direction.all
111
+ end
112
+ def self.wayback_binding
113
+ { "A" => "straight_forward", "R" => "backward"}
114
+ end
115
+ def wayback_code
116
+ return nil if self.class.wayback_binding[wayback].nil?
117
+ Chouette::Wayback.new( self.class.wayback_binding[wayback])
118
+ end
119
+ def wayback_code=(wayback_code)
120
+ self.wayback = nil
121
+ self.class.wayback_binding.each do |k,v|
122
+ self.wayback = k if v==wayback_code
123
+ end
124
+ end
125
+ @@waybacks = nil
126
+ def self.waybacks
127
+ @@waybacks ||= Chouette::Wayback.all
128
+ end
129
+
130
+ def stop_point_permutation?( stop_point_ids)
131
+ stop_points.map(&:id).map(&:to_s).sort == stop_point_ids.map(&:to_s).sort
132
+ end
133
+
134
+ def reorder!( stop_point_ids)
135
+ return false unless stop_point_permutation?( stop_point_ids)
136
+
137
+ stop_area_id_by_stop_point_id = {}
138
+ stop_points.each do |sp|
139
+ stop_area_id_by_stop_point_id.merge!( sp.id => sp.stop_area_id)
140
+ end
141
+
142
+ reordered_stop_area_ids = []
143
+ stop_point_ids.each do |stop_point_id|
144
+ reordered_stop_area_ids << stop_area_id_by_stop_point_id[ stop_point_id.to_i]
145
+ end
146
+
147
+ stop_points.each_with_index do |sp, index|
148
+ if sp.stop_area_id.to_s != reordered_stop_area_ids[ index].to_s
149
+ #result = sp.update_attributes( :stop_area_id => reordered_stop_area_ids[ index])
150
+ sp.stop_area_id = reordered_stop_area_ids[ index]
151
+ result = sp.save!
152
+ end
153
+ end
154
+
155
+ return true
156
+ end
157
+ end
158
+
@@ -0,0 +1,273 @@
1
+ require 'geokit'
2
+ require 'geo_ruby'
3
+
4
+ class Chouette::StopArea < Chouette::TridentActiveRecord
5
+ # FIXME http://jira.codehaus.org/browse/JRUBY-6358
6
+ set_primary_key :id
7
+ include Geokit::Mappable
8
+ has_many :stop_points, :dependent => :destroy
9
+ has_many :access_points, :dependent => :destroy
10
+ has_many :access_links, :dependent => :destroy
11
+ has_and_belongs_to_many :routing_lines, :class_name => 'Chouette::Line', :foreign_key => "stop_area_id", :association_foreign_key => "line_id", :join_table => "routing_constraints_lines", :order => "lines.number"
12
+ has_and_belongs_to_many :routing_stops, :class_name => 'Chouette::StopArea', :foreign_key => "parent_id", :association_foreign_key => "child_id", :join_table => "stop_areas_stop_areas", :order => "stop_areas.name"
13
+
14
+ acts_as_tree :foreign_key => 'parent_id',:order => "name"
15
+
16
+ attr_accessor :stop_area_type
17
+ attr_accessor :children_ids
18
+
19
+ attr_accessible :routing_stop_ids, :routing_line_ids, :children_ids, :stop_area_type, :parent_id, :objectid
20
+ attr_accessible :object_version, :creation_time, :creator_id, :name, :comment, :area_type, :registration_number
21
+ attr_accessible :nearest_topic_name, :fare_code, :longitude, :latitude, :long_lat_type, :x, :y, :projection_type
22
+ attr_accessible :country_code, :street_name
23
+
24
+ # workaround of ruby 1.8 private method y block attribute y reading access
25
+ def y
26
+ read_attribute :y
27
+ end
28
+
29
+ validates_uniqueness_of :registration_number, :allow_nil => true, :allow_blank => true
30
+ validates_format_of :registration_number, :with => %r{\A[0-9A-Za-z_-]+\Z}, :allow_blank => true
31
+ validates_presence_of :name
32
+ validates_presence_of :area_type
33
+
34
+ validates_presence_of :latitude, :if => :longitude
35
+ validates_presence_of :longitude, :if => :latitude
36
+ validates_numericality_of :latitude, :less_than_or_equal_to => 90, :greater_than_or_equal_to => -90, :allow_nil => true
37
+ validates_numericality_of :longitude, :less_than_or_equal_to => 180, :greater_than_or_equal_to => -180, :allow_nil => true
38
+
39
+ validates_presence_of :x, :if => :y
40
+ validates_presence_of :y, :if => :x
41
+ validates_numericality_of :x, :allow_nil => true
42
+ validates_numericality_of :y, :allow_nil => true
43
+
44
+ def self.nullable_attributes
45
+ [:registration_number, :street_name, :country_code, :fare_code, :nearest_topic_name, :comment, :projection_type, :long_lat_type]
46
+ end
47
+
48
+ after_update :clean_invalid_access_links
49
+
50
+ def children_in_depth
51
+ return [] if self.children.empty?
52
+
53
+ self.children + self.children.map do |child|
54
+ child.children_in_depth
55
+ end.flatten.compact
56
+ end
57
+
58
+ def possible_children
59
+ case area_type
60
+ when "BoardingPosition" then []
61
+ when "Quay" then []
62
+ when "CommercialStopPoint" then Chouette::StopArea.where(:area_type => ['Quay', 'BoardingPosition']) - [self]
63
+ when "StopPlace" then Chouette::StopArea.where(:area_type => ['StopPlace', 'CommercialStopPoint']) - [self]
64
+ when "ITL" then Chouette::StopArea.where(:area_type => ['Quay', 'BoardingPosition', 'StopPlace', 'CommercialStopPoint'])
65
+ end
66
+
67
+ end
68
+
69
+ def possible_parents
70
+ case area_type
71
+ when "BoardingPosition" then Chouette::StopArea.where(:area_type => "CommercialStopPoint") - [self]
72
+ when "Quay" then Chouette::StopArea.where(:area_type => "CommercialStopPoint") - [self]
73
+ when "CommercialStopPoint" then Chouette::StopArea.where(:area_type => "StopPlace") - [self]
74
+ when "StopPlace" then Chouette::StopArea.where(:area_type => "StopPlace") - [self]
75
+ end
76
+ end
77
+
78
+ def lines
79
+ if (area_type == 'CommercialStopPoint')
80
+ self.children.collect(&:stop_points).flatten.collect(&:route).flatten.collect(&:line).flatten.uniq
81
+ else
82
+ self.stop_points.collect(&:route).flatten.collect(&:line).flatten.uniq
83
+ end
84
+ end
85
+
86
+ def routes
87
+ self.stop_points.collect(&:route).flatten.uniq
88
+ end
89
+
90
+ def self.commercial
91
+ where :area_type => "CommercialStopPoint"
92
+ end
93
+
94
+ def to_lat_lng
95
+ Geokit::LatLng.new(latitude, longitude) if latitude and longitude
96
+ end
97
+
98
+ def geometry
99
+ GeoRuby::SimpleFeatures::Point.from_lon_lat(longitude, latitude, 4326) if latitude and longitude
100
+ end
101
+
102
+ def geometry=(geometry)
103
+ geometry = geometry.to_wgs84
104
+ self.latitude, self.longitude, self.long_lat_type = geometry.lat, geometry.lng, "WGS84"
105
+ end
106
+
107
+ def position
108
+ geometry
109
+ end
110
+
111
+ def position=(position)
112
+ position = nil if String === position && position == ""
113
+ position = Geokit::LatLng.normalize(position), 4326 if String === position
114
+ self.latitude = position.lat
115
+ self.longitude = position.lng
116
+ end
117
+
118
+ def default_position
119
+ # for first StopArea ... the bounds is nil :(
120
+ Chouette::StopArea.bounds and Chouette::StopArea.bounds.center
121
+ end
122
+
123
+ def self.near(origin, distance = 0.3)
124
+ origin = origin.to_lat_lng
125
+
126
+ lat_degree_units = units_per_latitude_degree(:kms)
127
+ lng_degree_units = units_per_longitude_degree(origin.lat, :kms)
128
+
129
+ where "SQRT(POW(#{lat_degree_units}*(#{origin.lat}-latitude),2)+POW(#{lng_degree_units}*(#{origin.lng}-longitude),2)) <= #{distance}"
130
+ end
131
+
132
+ def self.bounds
133
+ # Give something like :
134
+ # [["113.5292500000000000", "22.1127580000000000", "113.5819330000000000", "22.2157050000000000"]]
135
+ min_and_max = connection.select_rows("select min(longitude) as min_lon, min(latitude) as min_lat, max(longitude) as max_lon, max(latitude) as max_lat from #{table_name} where latitude is not null and longitude is not null").first
136
+ return nil unless min_and_max
137
+
138
+ # Ignore [nil, nil, nil, nil]
139
+ min_and_max.compact!
140
+ return nil unless min_and_max.size == 4
141
+
142
+ min_and_max.collect! { |n| n.to_f }
143
+
144
+ # We need something like :
145
+ # [[113.5292500000000000, 22.1127580000000000], [113.5819330000000000, 22.2157050000000000]]
146
+ coordinates = min_and_max.each_slice(2).to_a
147
+ GeoRuby::SimpleFeatures::Envelope.from_coordinates coordinates
148
+ end
149
+
150
+ def stop_area_type
151
+ area_type && Chouette::AreaType.new(area_type.underscore)
152
+ end
153
+
154
+ def stop_area_type=(stop_area_type)
155
+ self.area_type = (stop_area_type ? stop_area_type.camelcase : nil)
156
+ if self.area_type == 'Itl'
157
+ self.area_type = 'ITL'
158
+ end
159
+ end
160
+
161
+ @@stop_area_types = nil
162
+ def self.stop_area_types
163
+ @@stop_area_types ||= Chouette::AreaType.all.select do |stop_area_type|
164
+ stop_area_type.to_i >= 0
165
+ end
166
+ end
167
+
168
+ def children_ids=(children_ids)
169
+ children = children_ids.split(',').uniq
170
+ # remove unset children
171
+ self.children.each do |child|
172
+ if (! children.include? child.id)
173
+ child.update_attribute :parent_id, nil
174
+ end
175
+ end
176
+ # add new children
177
+ Chouette::StopArea.find(children).each do |child|
178
+ child.update_attribute :parent_id, self.id
179
+ end
180
+ end
181
+
182
+ def routing_stop_ids=(routing_stop_ids)
183
+ stops = routing_stop_ids.split(',').uniq
184
+ self.routing_stops.clear
185
+ Chouette::StopArea.find(stops).each do |stop|
186
+ self.routing_stops << stop
187
+ end
188
+ end
189
+
190
+ def routing_line_ids=(routing_line_ids)
191
+ lines = routing_line_ids.split(',').uniq
192
+ self.routing_lines.clear
193
+ Chouette::Line.find(lines).each do |line|
194
+ self.routing_lines << line
195
+ end
196
+ end
197
+
198
+ def self.without_geometry
199
+ where("latitude is null or longitude is null")
200
+ end
201
+
202
+ def self.with_geometry
203
+ where("latitude is not null and longitude is not null")
204
+ end
205
+
206
+ def self.default_geometry!
207
+ count = 0
208
+ scoped.find_each do |stop_area|
209
+ Chouette::StopArea.unscoped do
210
+ count += 1 if stop_area.default_geometry!
211
+ end
212
+ end
213
+ count
214
+ end
215
+
216
+ def default_geometry!
217
+ new_geometry = default_geometry
218
+ update_attribute :geometry, new_geometry if new_geometry
219
+ end
220
+
221
+ def default_geometry
222
+ children_geometries = children.with_geometry.map(&:geometry).uniq
223
+ GeoRuby::SimpleFeatures::Point.centroid children_geometries if children_geometries.present?
224
+ end
225
+
226
+ def generic_access_link_matrix
227
+ matrix = Array.new
228
+ access_points.each do |access_point|
229
+ matrix += access_point.generic_access_link_matrix
230
+ end
231
+ matrix
232
+ end
233
+
234
+ def detail_access_link_matrix
235
+ matrix = Array.new
236
+ access_points.each do |access_point|
237
+ matrix += access_point.detail_access_link_matrix
238
+ end
239
+ matrix
240
+ end
241
+
242
+ def children_at_base
243
+ list = Array.new
244
+ children_in_depth.each do |child|
245
+ if child.area_type == 'Quay' || child.area_type == 'BoardingPosition'
246
+ list << child
247
+ end
248
+ end
249
+ list
250
+ end
251
+
252
+ def parents
253
+ list = Array.new
254
+ if !parent.nil?
255
+ list << parent
256
+ list += parent.parents
257
+ end
258
+ list
259
+ end
260
+
261
+ def clean_invalid_access_links
262
+ stop_parents = parents
263
+ access_links.each do |link|
264
+ unless stop_parents.include? link.access_point.stop_area
265
+ link.delete
266
+ end
267
+ end
268
+ children.each do |child|
269
+ child.clean_invalid_access_links
270
+ end
271
+ end
272
+
273
+ end
@@ -0,0 +1,33 @@
1
+ class Chouette::StopPoint < Chouette::TridentActiveRecord
2
+ # FIXME http://jira.codehaus.org/browse/JRUBY-6358
3
+ set_primary_key :id
4
+
5
+ belongs_to :stop_area
6
+ belongs_to :route
7
+ acts_as_list :scope => 'route_id = \'#{route.id}\'',:top_of_list => 0
8
+
9
+ attr_accessible :route_id, :stop_area_id, :objectid, :object_version, :creation_time, :creator_id, :position
10
+
11
+ has_many :vehicle_journey_at_stops, :dependent => :destroy
12
+ has_many :vehicle_journeys, :through => :vehicle_journey_at_stops, :uniq => true
13
+
14
+ before_destroy :remove_dependent_journey_pattern_stop_points
15
+
16
+ validates_presence_of :stop_area
17
+ validates_presence_of :route
18
+
19
+ scope :default_order, order("position")
20
+
21
+ def self.area_candidates
22
+ Chouette::StopArea.where( :area_type => ['Quay', 'BoardingPosition'])
23
+ end
24
+
25
+ def remove_dependent_journey_pattern_stop_points
26
+ route.journey_patterns.each do |jp|
27
+ if jp.stop_point_ids.include?( id)
28
+ jp.stop_point_ids = jp.stop_point_ids - [id]
29
+ end
30
+ end
31
+ end
32
+
33
+ end