Class: PostRunner::FitFileStore
- Inherits:
-
PEROBS::Object
- Object
- PEROBS::Object
- PostRunner::FitFileStore
- Includes:
- DirUtils
- Defined in:
- lib/postrunner/FitFileStore.rb
Overview
The FitFileStore stores all FIT file and provides access to the contained data.
Instance Attribute Summary collapse
-
#store ⇒ Object
readonly
Returns the value of attribute store.
-
#views ⇒ Object
readonly
Returns the value of attribute views.
Instance Method Summary collapse
-
#activities ⇒ Array of FFS_Activity
List of stored activities.
-
#add_fit_file(fit_file_name, fit_entity = nil, overwrite = false) ⇒ FFS_Activity or FFS_Monitoring
Add a file to the store.
-
#change_unit_system ⇒ Object
Perform the necessary report updates after the unit system has been changed.
-
#check ⇒ Object
This methods checks all stored FIT files for correctness, updates all indexes and re-generates all HTML reports.
-
#delete_activity(activity) ⇒ Object
Delete an activity from the database.
-
#devices ⇒ Array of FFS_Device
List of registered devices.
-
#find(query) ⇒ Object
Find a specific subset of the activities based on their index.
-
#fit_file_dir(fit_file_base_name, long_uid, type) ⇒ String
Determine the right directory for the given FIT file.
-
#handle_version_update ⇒ Object
Version upgrade logic.
-
#initialize(p) ⇒ FitFileStore
constructor
Create a new FIT file store.
- #list_activities ⇒ Object
-
#predecessor(activity) ⇒ Object
Return the previous Activity before the provided activity.
-
#ref_by_activity(activity) ⇒ Fixnum
Return the reference index of the given FFS_Activity.
-
#rename_activity(activity, name) ⇒ Object
Rename the specified activity and update all HTML pages that contain the name.
-
#restore ⇒ Object
Setup non-persistent variables.
-
#set_activity_attribute(activity, attribute, value) ⇒ Object
Set the specified attribute of the given activity to a new value.
-
#show_in_browser(html_file) ⇒ Object
Launch a web browser and show an HTML file.
-
#show_list_in_browser ⇒ Object
Show the activity list in a web browser.
-
#successor(activity) ⇒ Object
Return the next Activity after the provided activity.
Methods included from DirUtils
Constructor Details
#initialize(p) ⇒ FitFileStore
Create a new FIT file store.
36 37 38 39 |
# File 'lib/postrunner/FitFileStore.rb', line 36 def initialize(p) super(p) restore end |
Instance Attribute Details
#store ⇒ Object (readonly)
Returns the value of attribute store.
32 33 34 |
# File 'lib/postrunner/FitFileStore.rb', line 32 def store @store end |
#views ⇒ Object (readonly)
Returns the value of attribute views.
32 33 34 |
# File 'lib/postrunner/FitFileStore.rb', line 32 def views @views end |
Instance Method Details
#activities ⇒ Array of FFS_Activity
Returns List of stored activities.
205 206 207 208 209 210 211 |
# File 'lib/postrunner/FitFileStore.rb', line 205 def activities list = [] @store['devices'].each do |id, device| list += device.activities end list.sort end |
#add_fit_file(fit_file_name, fit_entity = nil, overwrite = false) ⇒ FFS_Activity or FFS_Monitoring
Add a file to the store.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/postrunner/FitFileStore.rb', line 76 def add_fit_file(fit_file_name, fit_entity = nil, overwrite = false) # If we the file hasn't been read yet, read it in as a # Fit4Ruby::Activity or Fit4Ruby::Monitoring entity. unless fit_entity return nil unless (fit_entity = read_fit_file(fit_file_name)) end unless [ Fit4Ruby::Activity, Fit4Ruby::Monitoring ].include?(fit_entity.class) Log.critical "Unsupported FIT file type #{fit_entity.class}" end # Generate a String that uniquely identifies the device that generated # the FIT file. id = extract_fit_file_id(fit_entity) long_uid = "#{id[:manufacturer]}-#{id[:product]}-#{id[:serial_number]}" # Make sure the device that created the FIT file is properly registered. device = register_device(long_uid) # Store the FIT entity with the device. entity = device.add_fit_file(fit_file_name, fit_entity, overwrite) # The FIT file might be already stored or invalid. In that case we # abort this method. return nil unless entity if fit_entity.is_a?(Fit4Ruby::Activity) @store['records'].scan_activity_for_records(entity) # Generate HTML file for this activity. entity.generate_html_report # The HTML activity views contain links to their predecessors and # successors. After inserting a new activity, we need to re-generate # these views as well. if (pred = predecessor(entity)) pred.generate_html_report end if (succ = successor(entity)) succ.generate_html_report end # And update the index pages generate_html_index_pages end Log.info "#{File.basename(fit_file_name)} " + 'has been successfully added to archive' entity end |
#change_unit_system ⇒ Object
Perform the necessary report updates after the unit system has been changed.
174 175 176 177 178 179 180 181 182 |
# File 'lib/postrunner/FitFileStore.rb', line 174 def change_unit_system # If we have changed the unit system we need to re-generate all HTML # reports. activities.each do |activity| activity.generate_html_report end @store['records'].generate_html_reports generate_html_index_pages end |
#check ⇒ Object
This methods checks all stored FIT files for correctness, updates all indexes and re-generates all HTML reports.
286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/postrunner/FitFileStore.rb', line 286 def check records = @store['records'] records.delete_all_records activities.sort do |a1, a2| a1. <=> a2. end.each do |a| a.check records.scan_activity_for_records(a) end records.generate_html_reports generate_html_index_pages end |
#delete_activity(activity) ⇒ Object
Delete an activity from the database. It will only delete the entry in the database. The original activity file will not be deleted from the file system.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/postrunner/FitFileStore.rb', line 131 def delete_activity(activity) pred = predecessor(activity) succ = successor(activity) activity.device.delete_activity(activity) # The HTML activity views contain links to their predecessors and # successors. After deleting an activity, we need to re-generate these # views. pred.generate_html_report if pred succ.generate_html_report if succ generate_html_index_pages end |
#devices ⇒ Array of FFS_Device
Returns List of registered devices.
200 201 202 |
# File 'lib/postrunner/FitFileStore.rb', line 200 def devices @store['devices'] end |
#find(query) ⇒ Object
Find a specific subset of the activities based on their index.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/postrunner/FitFileStore.rb', line 243 def find(query) case query when /\A-?\d+$\z/ index = query.to_i # The UI counts the activities from 1 to N. Ruby counts from 0 - # (N-1). if index <= 0 Log.error 'Index must be larger than 0' return [] end # The UI counts the activities from 1 to N. Ruby counts from 0 - # (N-1). if (a = activities[index - 1]) return [ a ] end when /\A-?\d+--?\d+\z/ idxs = query.match(/(?<sidx>-?\d+)-(?<eidx>-?[0-9]+)/) if (sidx = idxs['sidx'].to_i) <= 0 Log.error 'Start index must be larger than 0' return [] end if (eidx = idxs['eidx'].to_i) <= 0 Log.error 'End index must be larger than 0' return [] end if eidx < sidx Log.error 'Start index must be smaller than end index' return [] end # The UI counts the activities from 1 to N. Ruby counts from 0 - # (N-1). unless (as = activities[(sidx - 1)..(eidx - 1)]).empty? return as end else Log.error "Invalid activity query: #{query}" end [] end |
#fit_file_dir(fit_file_base_name, long_uid, type) ⇒ String
Determine the right directory for the given FIT file. The resulting path looks something like /home/user/.postrunner/devices/garmin-fenix3-1234/ activity/5A.
190 191 192 193 194 195 |
# File 'lib/postrunner/FitFileStore.rb', line 190 def fit_file_dir(fit_file_base_name, long_uid, type) # The first letter of the FIT file specifies the creation year. # The second letter of the FIT file specifies the creation month. File.join(@store['config']['devices_dir'], long_uid, type, fit_file_base_name[0..1]) end |
#handle_version_update ⇒ Object
Version upgrade logic.
66 67 68 |
# File 'lib/postrunner/FitFileStore.rb', line 66 def handle_version_update # Nothing here so far. end |
#list_activities ⇒ Object
306 307 308 |
# File 'lib/postrunner/FitFileStore.rb', line 306 def list_activities puts ActivityListView.new(self).to_s end |
#predecessor(activity) ⇒ Object
Return the previous Activity before the provided activity. If none is found, return nil.
233 234 235 236 237 238 239 |
# File 'lib/postrunner/FitFileStore.rb', line 233 def predecessor(activity) all_activities = activities idx = all_activities.index(activity) return nil if idx.nil? # Activities indexes are reversed. The predecessor has a higher index. all_activities[idx + 1] end |
#ref_by_activity(activity) ⇒ Fixnum
Return the reference index of the given FFS_Activity.
216 217 218 219 220 |
# File 'lib/postrunner/FitFileStore.rb', line 216 def ref_by_activity(activity) return nil unless (idx = activities.index(activity)) idx + 1 end |
#rename_activity(activity, name) ⇒ Object
Rename the specified activity and update all HTML pages that contain the name.
150 151 152 153 154 |
# File 'lib/postrunner/FitFileStore.rb', line 150 def rename_activity(activity, name) activity.set('name', name) generate_html_index_pages @store['records'].generate_html_reports if activity.has_records? end |
#restore ⇒ Object
Setup non-persistent variables.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/postrunner/FitFileStore.rb', line 42 def restore @data_dir = @store['config']['data_dir'] # Ensure that we have an Array in the store to hold all known devices. @store['devices'] = @store.new(PEROBS::Hash) unless @store['devices'] @devices_dir = File.join(@data_dir, 'devices') # It's generally not a good idea to store absolute file names in the # database. We'll make an exception here as this is the only way to # propagate this path to FFS_Activity or FFS_Monitoring objects. The # store entry is updated on each program run, so the DB can be moved # safely to another directory. @store['config']['devices_dir'] = @devices_dir create_directory(@devices_dir, 'devices') # Define which View objects the HTML output will consist of. This # doesn't really belong in this class but for now it's the best place # to put it. @views = ViewButtons.new([ NavButtonDef.new('activities.png', 'index.html'), NavButtonDef.new('record.png', "records-0.html") ]) end |
#set_activity_attribute(activity, attribute, value) ⇒ Object
Set the specified attribute of the given activity to a new value.
160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/postrunner/FitFileStore.rb', line 160 def set_activity_attribute(activity, attribute, value) activity.set(attribute, value) case attribute when 'norecord', 'type' # If we have changed a norecord setting or an activity type, we need # to regenerate all reports and re-collect the record list since we # don't know which Activity needs to replace the changed one. check end generate_html_index_pages end |
#show_in_browser(html_file) ⇒ Object
Launch a web browser and show an HTML file.
312 313 314 315 316 317 318 319 |
# File 'lib/postrunner/FitFileStore.rb', line 312 def show_in_browser(html_file) cmd = "#{ENV['BROWSER'] || 'firefox'} \"#{html_file}\" &" unless system(cmd) Log.fatal "Failed to execute the following shell command: #{$cmd}\n" + "#{$!}" end end |
#show_list_in_browser ⇒ Object
Show the activity list in a web browser.
300 301 302 303 304 |
# File 'lib/postrunner/FitFileStore.rb', line 300 def show_list_in_browser generate_html_index_pages @store['records'].generate_html_reports show_in_browser(File.join(@store['config']['html_dir'], 'index.html')) end |
#successor(activity) ⇒ Object
Return the next Activity after the provided activity. Note that this has a lower index. If none is found, return nil.
224 225 226 227 228 229 |
# File 'lib/postrunner/FitFileStore.rb', line 224 def successor(activity) all_activities = activities idx = all_activities.index(activity) return nil if idx.nil? || idx == 0 all_activities[idx - 1] end |