fit_kit 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cfc4c2435b6e655fe41d4e467e373b5b282eaab6f738922d1d5a93721c8adaaa
4
- data.tar.gz: a1ab87078789a8e83fc13d9f2ee39bf4e060d35f2b290adbadd95e4def05afcf
3
+ metadata.gz: 6f5d819105551844f5a7e45a8399aa60b403cbc5b8b2adb278c0fb9a8a29631c
4
+ data.tar.gz: 1a55ae0af1a09860935dc3dee596a191c42133ae2a070c7c788514e4b4694248
5
5
  SHA512:
6
- metadata.gz: 2c25a7c3cb74581d959c406c89fa8a1df686c7632e52c52cab58c3b3a9bd1771e90ef7b0d2c67ae386e21a12d45eed52759dd951bc14b8b2a8622877d88d095c
7
- data.tar.gz: bc93a12200a50dd2d7cdaf4e9eaf165a7308ca59e83640ac26cd4b701305cda9a9b0e7908b885a7d55d4ec1281c5dc62db0b5ffbd57705ff1f8153c4ddb1ce4e
6
+ metadata.gz: 46cd84be49270a1197f815f776cc51627ba58d7abf72d8f0f4b6d80cb9f485ceca1a73745eb62df2696fe2a0cd3b78e2311550bf3f711dfcaf133daeed3abf1e
7
+ data.tar.gz: 32993953f6611a2ad85a70426be7525bb558e3cdf201e994e6848d04ab29f8ebdee3e1d722ac432173f05e799196f47a8f38e3d73c6f151c7de83497cdfa3463
data/README.md CHANGED
@@ -20,6 +20,50 @@ fit_data_records = ::FitKit.parse_fit_file(test_fit_file)
20
20
  # [RFitDataRecord, RFitDataRecord, RFitDataRecord ...]
21
21
  ```
22
22
 
23
+ ## Performance
24
+ Here is the performance parsing __4090__ fit files on my M1 Mac Mini (16G, 8 Cores) took 6 seconds (in parallel):
25
+
26
+ ```txt
27
+ ❯ ruby app.rb
28
+ Parsing 4090 fit files...
29
+ user system total real
30
+ 0.129862 0.102642 45.192900 ( 6.121117)
31
+ ```
32
+
33
+ Code to parse a given folder (contains __4090__ fit files) in parallel:
34
+
35
+ ```ruby
36
+ require 'fit_kit'
37
+ require 'benchmark'
38
+ require 'parallel'
39
+
40
+ def parse_concurrently
41
+ puts "Parsing all fit files here"
42
+ fit_files = Dir.glob("/Users/mikeli/docs/HealthFit/*.{fit,FIT}")
43
+ puts "Parsing #{fit_files.size} fit files..."
44
+
45
+ # Determine the number of processors
46
+ num_processors = Parallel.processor_count
47
+
48
+ # Parse files concurrently
49
+ Parallel.each(fit_files, in_processes: num_processors) do |file|
50
+ begin
51
+ FitKit.parse_fit_file(file)
52
+ rescue => e
53
+ puts "Error parsing #{file}: #{e.message}"
54
+ end
55
+ end
56
+ end
57
+
58
+
59
+ Benchmark.bm do |x|
60
+ x.report do
61
+ parse_concurrently
62
+ end
63
+ end
64
+
65
+ ```
66
+
23
67
  ## Contributing
24
68
 
25
69
  Bug reports and pull requests are welcome on GitHub at https://github.com/29decibel/fit_kit. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/29decibel/fit_kit/blob/main/CODE_OF_CONDUCT.md).
@@ -1,12 +1,7 @@
1
- use fitparser::{self, FitDataField, FitDataRecord, Value};
2
- use magnus::{function, method, prelude::*, Error, IntoValue, RArray, Ruby};
1
+ use fitparser::{self, FitDataRecord, Value};
2
+ use magnus::{function, method, prelude::*, Error, IntoValue, RArray, RHash, Ruby, Symbol};
3
3
  use std::fs::File;
4
4
 
5
- ///////////////////////// RFitDataField ///////////////////////////
6
- // define a wrapper ruby class for FitDataField
7
- #[magnus::wrap(class = "RFitDataField")]
8
- struct RFitDataField(FitDataField);
9
-
10
5
  // recursive method to turn Fit value into magnus::Value
11
6
  fn value_to_rb_value(value: &Value) -> magnus::Value {
12
7
  match value {
@@ -38,16 +33,6 @@ fn value_to_rb_value(value: &Value) -> magnus::Value {
38
33
  }
39
34
  }
40
35
 
41
- impl RFitDataField {
42
- fn name(&self) -> String {
43
- self.0.name().to_string()
44
- }
45
-
46
- fn value(&self) -> magnus::Value {
47
- value_to_rb_value(self.0.value())
48
- }
49
- }
50
-
51
36
  ///////////////////////// RFitDataRecord ///////////////////////////
52
37
  #[magnus::wrap(class = "RFitDataRecord")]
53
38
  struct RFitDataRecord(FitDataRecord);
@@ -57,28 +42,29 @@ impl RFitDataRecord {
57
42
  self.0.kind().to_string()
58
43
  }
59
44
 
60
- fn fields(&self) -> RArray {
61
- let array = RArray::new();
45
+ fn fields_hash(&self) -> RHash {
46
+ let hash = RHash::new();
62
47
  for field in self.0.fields() {
63
- array.push(RFitDataField(field.clone())).unwrap();
48
+ let value = value_to_rb_value(field.value());
49
+ let pair = RHash::new();
50
+ pair.aset(Symbol::new("units"), field.units()).unwrap();
51
+ pair.aset(Symbol::new("value"), value).unwrap();
52
+ // here we add the stuff to the hash
53
+ let field_name_symbol = Symbol::new(field.name());
54
+ hash.aset(field_name_symbol, pair).unwrap();
64
55
  }
65
- array
56
+
57
+ hash
66
58
  }
67
59
  }
68
60
 
69
61
  // Here we define two ruby classes
70
62
  // RFitDataRecord and RFitDataField
71
63
  fn define_ruby_classes(ruby: &Ruby) -> Result<(), magnus::Error> {
72
- let class = ruby.define_class("RFitDataField", ruby.class_object())?;
73
-
74
- // define bunch of methods
75
- class.define_method("name", method!(RFitDataField::name, 0))?;
76
- class.define_method("value", method!(RFitDataField::value, 0))?;
77
-
78
64
  // definie the the other one here
79
65
  let data_record_class = ruby.define_class("RFitDataRecord", ruby.class_object())?;
80
66
  data_record_class.define_method("kind", method!(RFitDataRecord::kind, 0))?;
81
- data_record_class.define_method("fields", method!(RFitDataRecord::fields, 0))?;
67
+ data_record_class.define_method("fields_hash", method!(RFitDataRecord::fields_hash, 0))?;
82
68
 
83
69
  Ok(())
84
70
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FitKit
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fit_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - 29decibel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-15 00:00:00.000000000 Z
11
+ date: 2024-10-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Garmin fit file parser wrapping Rust crate fitparse_rs.
14
14
  email: