Class: Itinerary

Inherits:
Object
  • Object
show all
Defined in:
lib/itinerary.rb,
lib/itinerary/tool.rb,
lib/itinerary/view.rb,
lib/itinerary/record.rb,
lib/itinerary/version.rb,
lib/itinerary/views/kml.rb,
lib/itinerary/views/tab.rb,
lib/itinerary/tools/list.rb,
lib/itinerary/views/html.rb,
lib/itinerary/views/text.rb,
lib/itinerary/tools/create.rb,
lib/itinerary/tools/import.rb,
lib/itinerary/tools/convert.rb,
lib/itinerary/tools/find-dups.rb,
lib/itinerary/tools/scrape-briar.rb

Overview

require ‘itinerary/briar_scraper’

Defined Under Namespace

Classes: ConvertTool, CreateTool, FindDupsTool, ImportTool, ListTool, Record, ScrapeBriar, Tool, View

Constant Summary collapse

DefaultRadius =
100
VERSION =
'0.1'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Itinerary

Returns a new instance of Itinerary.



27
28
29
30
31
32
33
34
35
36
# File 'lib/itinerary.rb', line 27

def initialize(options={})
  @name = options[:name]
  @root = options[:root] or raise "Must specify root"
  @root = Pathname.new(@root).expand_path
  @geocoding_cache_path = options[:geocoding_cache] || '.geocoding-cache'
  setup_geocoding_cache
  @entries = []
  read_entries
  read_routes
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



23
24
25
# File 'lib/itinerary.rb', line 23

def name
  @name
end

#rootObject

Returns the value of attribute root.



24
25
26
# File 'lib/itinerary.rb', line 24

def root
  @root
end

#routeObject

Returns the value of attribute route.



25
26
27
# File 'lib/itinerary.rb', line 25

def route
  @route
end

Instance Method Details

#[](path) ⇒ Object



152
153
154
# File 'lib/itinerary.rb', line 152

def [](path)
  @entries.find { |r| r.path == path }
end

#cleanupObject



38
39
40
# File 'lib/itinerary.rb', line 38

def cleanup
  @geocoding_cache.close
end

#entries(filters = nil) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/itinerary.rb', line 104

def entries(filters=nil)
  matched = @entries.dup
  ;;warn "[entries] filtering #{matched.length} entries: #{filters.inspect}"
  if filters
    filters.each do |key, value|
      case key
      when :near
        coordinates = case value
        when Array
          value
        when Pathname
          rec = self[value] or raise "Record #{value.inspect} not found"
          raise "#{rec.path} is not geocoded" unless rec.geocoded?
          rec.coordinates
        when String
          results = Geocoder.search(value)
          result = results.first or raise "Can't find location #{value.inspect}"
          result.coordinates
        end
        raise "No coordinates found for #{value.inspect}" unless coordinates
        matched.select! { |r| r.near(coordinates, filters[:radius] || DefaultRadius) }
      when :radius
        # ignored here -- used above
      when :flags
        matched.select! do |rec|
          value.find { |v| rec.method("#{v}?").call }
        end
      else
        raise "Unknown field: #{key.inspect}" unless Record.field(key) || Record.instance_methods.include?(key)
        matched.select! { |r| r[key] == value }
      end
    end
  end
  ;;warn "[entries] filtered #{matched.length} entries: #{filters.inspect}"
  matched
end

#entries_pathObject



42
43
44
# File 'lib/itinerary.rb', line 42

def entries_path
  @root + 'entries'
end

#geocode_search(place) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/itinerary.rb', line 81

def geocode_search(place)
  begin
    results = Geocoder.search(place)
    @geocoding_cache.flush
    result = results.first or raise "No geocoding result for place #{place.inspect}"
    HashStruct.new(
      :city => result.city,
      :state => result.state_code,
      :country => result.country_code,
      :latitude => result.coordinates[0],
      :longitude => result.coordinates[1])
  rescue => e
    warn "Error when geocoding place #{place.inspect}: #{e}"
    nil
  end
end

#import_entry(path) ⇒ Object



63
64
65
# File 'lib/itinerary.rb', line 63

def import_entry(path)
  @entries << Record.load(path)
end

#make_tool(cmd, args) ⇒ Object



98
99
100
101
102
# File 'lib/itinerary.rb', line 98

def make_tool(cmd, args)
  if (klass = Tool.find_tool(cmd))
    klass.new(self, args)
  end
end

#near(coords, radius) ⇒ Object



141
142
143
144
145
146
147
148
149
150
# File 'lib/itinerary.rb', line 141

def near(coords, radius)
  matches = {}
  @entries.each do |rec|
    if (distance = rec.near(coords, radius))
      matches[distance] ||= []
      matches[distance] << rec
    end
  end
  matches
end

#parse_params(params) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/itinerary.rb', line 156

def parse_params(params)
  filters = HashStruct.new
  options = HashStruct.new
  params.select.each do |key, value|
    case key.to_sym
    when :near
      filters.near = value
    when :radius
      filters.radius = value.to_f
    when :flags
      filters.flags = value.split(',').map { |f| f.to_sym }
    when :show_fields
      options.show_fields = value.split(',').map { |f| f.to_sym }
    when :hide_fields
      options.hide_fields = value.split(',').map { |f| f.to_sym }
    # when :fuzz
    #   options.fuzz_placemarks = value
    else
      filters[key.to_sym] = value
    end
  end
  [filters, options]
end

#read_entriesObject



50
51
52
53
54
55
56
57
# File 'lib/itinerary.rb', line 50

def read_entries
  ;;warn "[initialize] reading entries from #{entries_path}"
  entries_path.find do |path|
    import_entry(path) if path.file? && path.basename.to_s[0] != '.'
  end
  sort_entries
  ;;warn "[initialize] read #{@entries.length} entries"
end

#read_routesObject



67
68
69
70
71
72
73
# File 'lib/itinerary.rb', line 67

def read_routes
  ;;warn "[initialize] reading route from #{route_path}"
  if route_path.exist?
    @route = route_path.readlines.map { |p| geocode_search(p) }
  end
  ;;warn "[initialize] read #{@route.length} legs of route"
end

#route_pathObject



46
47
48
# File 'lib/itinerary.rb', line 46

def route_path
  @root + 'route'
end

#setup_geocoding_cacheObject



75
76
77
78
79
# File 'lib/itinerary.rb', line 75

def setup_geocoding_cache
  @geocoding_cache = Daybreak::DB.new(@geocoding_cache_path)
  @geocoding_cache.compact
  Geocoder.configure(:cache => @geocoding_cache)
end

#sort_entriesObject



59
60
61
# File 'lib/itinerary.rb', line 59

def sort_entries
  @entries.sort_by! { |r| r.visited || r.contacted || DateTime.now }
end